OSDN Git Service

5dfa67c9cf817fa65cb146b23364fcc2b4e9b954
[android-x86/external-swiftshader.git] / src / OpenGL / libGLES_CM / Framebuffer.cpp
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Framebuffer.cpp: Implements the Framebuffer class. Implements GL framebuffer
16 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
17
18 #include "Framebuffer.h"
19
20 #include "main.h"
21 #include "Renderbuffer.h"
22 #include "Texture.h"
23 #include "utilities.h"
24
25 namespace es1
26 {
27
28 Framebuffer::Framebuffer()
29 {
30         mColorbufferType = GL_NONE_OES;
31         mDepthbufferType = GL_NONE_OES;
32         mStencilbufferType = GL_NONE_OES;
33 }
34
35 Framebuffer::~Framebuffer()
36 {
37         mColorbufferPointer = nullptr;
38         mDepthbufferPointer = nullptr;
39         mStencilbufferPointer = nullptr;
40 }
41
42 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
43 {
44         Context *context = getContext();
45         Renderbuffer *buffer = nullptr;
46
47         if(type == GL_NONE_OES)
48         {
49                 buffer = nullptr;
50         }
51         else if(type == GL_RENDERBUFFER_OES)
52         {
53                 buffer = context->getRenderbuffer(handle);
54         }
55         else if(IsTextureTarget(type))
56         {
57                 buffer = context->getTexture(handle)->getRenderbuffer(type);
58         }
59         else UNREACHABLE(type);
60
61         return buffer;
62 }
63
64 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
65 {
66         mColorbufferType = (colorbuffer != 0) ? type : GL_NONE_OES;
67         mColorbufferPointer = lookupRenderbuffer(type, colorbuffer);
68 }
69
70 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
71 {
72         mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE_OES;
73         mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer);
74 }
75
76 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
77 {
78         mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE_OES;
79         mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer);
80 }
81
82 void Framebuffer::detachTexture(GLuint texture)
83 {
84         if(mColorbufferPointer.name() == texture && IsTextureTarget(mColorbufferType))
85         {
86                 mColorbufferType = GL_NONE_OES;
87                 mColorbufferPointer = nullptr;
88         }
89
90         if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType))
91         {
92                 mDepthbufferType = GL_NONE_OES;
93                 mDepthbufferPointer = nullptr;
94         }
95
96         if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType))
97         {
98                 mStencilbufferType = GL_NONE_OES;
99                 mStencilbufferPointer = nullptr;
100         }
101 }
102
103 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
104 {
105         if(mColorbufferPointer.name() == renderbuffer && mColorbufferType == GL_RENDERBUFFER_OES)
106         {
107                 mColorbufferType = GL_NONE_OES;
108                 mColorbufferPointer = nullptr;
109         }
110
111         if(mDepthbufferPointer.name() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER_OES)
112         {
113                 mDepthbufferType = GL_NONE_OES;
114                 mDepthbufferPointer = nullptr;
115         }
116
117         if(mStencilbufferPointer.name() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER_OES)
118         {
119                 mStencilbufferType = GL_NONE_OES;
120                 mStencilbufferPointer = nullptr;
121         }
122 }
123
124 // Increments refcount on surface.
125 // caller must Release() the returned surface
126 egl::Image *Framebuffer::getRenderTarget()
127 {
128         Renderbuffer *colorbuffer = mColorbufferPointer;
129
130         if(colorbuffer)
131         {
132                 return colorbuffer->getRenderTarget();
133         }
134
135         return nullptr;
136 }
137
138 // Increments refcount on surface.
139 // caller must Release() the returned surface
140 egl::Image *Framebuffer::getDepthBuffer()
141 {
142         Renderbuffer *depthbuffer = mDepthbufferPointer;
143
144         if(depthbuffer)
145         {
146                 return depthbuffer->getRenderTarget();
147         }
148
149         return nullptr;
150 }
151
152 // Increments refcount on surface.
153 // caller must Release() the returned surface
154 egl::Image *Framebuffer::getStencilBuffer()
155 {
156         Renderbuffer *stencilbuffer = mStencilbufferPointer;
157
158         if(stencilbuffer)
159         {
160                 return stencilbuffer->getRenderTarget();
161         }
162
163         return nullptr;
164 }
165
166 Renderbuffer *Framebuffer::getColorbuffer()
167 {
168         return mColorbufferPointer;
169 }
170
171 Renderbuffer *Framebuffer::getDepthbuffer()
172 {
173         return mDepthbufferPointer;
174 }
175
176 Renderbuffer *Framebuffer::getStencilbuffer()
177 {
178         return mStencilbufferPointer;
179 }
180
181 GLenum Framebuffer::getColorbufferType()
182 {
183         return mColorbufferType;
184 }
185
186 GLenum Framebuffer::getDepthbufferType()
187 {
188         return mDepthbufferType;
189 }
190
191 GLenum Framebuffer::getStencilbufferType()
192 {
193         return mStencilbufferType;
194 }
195
196 GLuint Framebuffer::getColorbufferName()
197 {
198         return mColorbufferPointer.name();
199 }
200
201 GLuint Framebuffer::getDepthbufferName()
202 {
203         return mDepthbufferPointer.name();
204 }
205
206 GLuint Framebuffer::getStencilbufferName()
207 {
208         return mStencilbufferPointer.name();
209 }
210
211 bool Framebuffer::hasStencil()
212 {
213         if(mStencilbufferType != GL_NONE_OES)
214         {
215                 Renderbuffer *stencilbufferObject = getStencilbuffer();
216
217                 if(stencilbufferObject)
218                 {
219                         return stencilbufferObject->getStencilSize() > 0;
220                 }
221         }
222
223         return false;
224 }
225
226 GLenum Framebuffer::completeness()
227 {
228         int width;
229         int height;
230         int samples;
231
232         return completeness(width, height, samples);
233 }
234
235 GLenum Framebuffer::completeness(int &width, int &height, int &samples)
236 {
237         width = -1;
238         height = -1;
239         samples = -1;
240
241         if(mColorbufferType != GL_NONE_OES)
242         {
243                 Renderbuffer *colorbuffer = getColorbuffer();
244
245                 if(!colorbuffer)
246                 {
247                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
248                 }
249
250                 if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
251                 {
252                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
253                 }
254
255                 if(mColorbufferType == GL_RENDERBUFFER_OES)
256                 {
257                         if(!IsColorRenderable(colorbuffer->getFormat()))
258                         {
259                                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
260                         }
261                 }
262                 else if(IsTextureTarget(mColorbufferType))
263                 {
264                         GLenum format = colorbuffer->getFormat();
265
266                         if(!IsColorRenderable(format))
267                         {
268                                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
269                         }
270
271                         if(IsDepthTexture(format) || IsStencilTexture(format))
272                         {
273                                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
274                         }
275                 }
276                 else
277                 {
278                         UNREACHABLE(mColorbufferType);
279                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
280                 }
281
282                 width = colorbuffer->getWidth();
283                 height = colorbuffer->getHeight();
284                 samples = colorbuffer->getSamples();
285         }
286
287         Renderbuffer *depthbuffer = nullptr;
288         Renderbuffer *stencilbuffer = nullptr;
289
290         if(mDepthbufferType != GL_NONE_OES)
291         {
292                 depthbuffer = getDepthbuffer();
293
294                 if(!depthbuffer)
295                 {
296                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
297                 }
298
299                 if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
300                 {
301                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
302                 }
303
304                 if(mDepthbufferType == GL_RENDERBUFFER_OES)
305                 {
306                         if(!es1::IsDepthRenderable(depthbuffer->getFormat()))
307                         {
308                                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
309                         }
310                 }
311                 else if(IsTextureTarget(mDepthbufferType))
312                 {
313                         if(!es1::IsDepthTexture(depthbuffer->getFormat()))
314                         {
315                                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
316                         }
317                 }
318                 else
319                 {
320                         UNREACHABLE(mDepthbufferType);
321                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
322                 }
323
324                 if(width == -1 || height == -1)
325                 {
326                         width = depthbuffer->getWidth();
327                         height = depthbuffer->getHeight();
328                         samples = depthbuffer->getSamples();
329                 }
330                 else if(width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
331                 {
332                         return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES;
333                 }
334                 else if(samples != depthbuffer->getSamples())
335                 {
336                         UNREACHABLE(0);
337                 }
338         }
339
340         if(mStencilbufferType != GL_NONE_OES)
341         {
342                 stencilbuffer = getStencilbuffer();
343
344                 if(!stencilbuffer)
345                 {
346                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
347                 }
348
349                 if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
350                 {
351                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
352                 }
353
354                 if(mStencilbufferType == GL_RENDERBUFFER_OES)
355                 {
356                         if(!es1::IsStencilRenderable(stencilbuffer->getFormat()))
357                         {
358                                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
359                         }
360                 }
361                 else if(IsTextureTarget(mStencilbufferType))
362                 {
363                         GLenum internalformat = stencilbuffer->getFormat();
364
365                         if(!es1::IsStencilTexture(internalformat))
366                         {
367                                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
368                         }
369                 }
370                 else
371                 {
372                         UNREACHABLE(mStencilbufferType);
373                         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
374                 }
375
376                 if(width == -1 || height == -1)
377                 {
378                         width = stencilbuffer->getWidth();
379                         height = stencilbuffer->getHeight();
380                         samples = stencilbuffer->getSamples();
381                 }
382                 else if(width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
383                 {
384                         return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES;
385                 }
386                 else if(samples != stencilbuffer->getSamples())
387                 {
388                         UNREACHABLE(0);
389                         return GL_FRAMEBUFFER_UNSUPPORTED_OES;   // GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_OES;
390                 }
391         }
392
393         // We need to have at least one attachment to be complete
394         if(width == -1 || height == -1)
395         {
396                 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES;
397         }
398
399         return GL_FRAMEBUFFER_COMPLETE_OES;
400 }
401
402 GLenum Framebuffer::getImplementationColorReadFormat()
403 {
404         Renderbuffer *colorbuffer = mColorbufferPointer;
405
406         if(colorbuffer)
407         {
408                 // Don't return GL_RGBA since that's always supported. Provide a second option here.
409                 switch(colorbuffer->getInternalFormat())
410                 {
411                 case sw::FORMAT_A8R8G8B8:      return GL_BGRA_EXT;
412                 case sw::FORMAT_A8B8G8R8:      return GL_BGRA_EXT;
413                 case sw::FORMAT_X8R8G8B8:      return 0x80E0;   // GL_BGR_EXT
414                 case sw::FORMAT_X8B8G8R8:      return 0x80E0;   // GL_BGR_EXT
415                 case sw::FORMAT_A1R5G5B5:      return GL_BGRA_EXT;
416                 case sw::FORMAT_R5G6B5:        return 0x80E0;   // GL_BGR_EXT
417                 default:
418                         UNREACHABLE(colorbuffer->getInternalFormat());
419                 }
420         }
421
422         return GL_RGBA;
423 }
424
425 GLenum Framebuffer::getImplementationColorReadType()
426 {
427         Renderbuffer *colorbuffer = mColorbufferPointer;
428
429         if(colorbuffer)
430         {
431                 switch(colorbuffer->getInternalFormat())
432                 {
433                 case sw::FORMAT_A8R8G8B8:      return GL_UNSIGNED_BYTE;
434                 case sw::FORMAT_A8B8G8R8:      return GL_UNSIGNED_BYTE;
435                 case sw::FORMAT_X8R8G8B8:      return GL_UNSIGNED_BYTE;
436                 case sw::FORMAT_X8B8G8R8:      return GL_UNSIGNED_BYTE;
437                 case sw::FORMAT_A1R5G5B5:      return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
438                 case sw::FORMAT_R5G6B5:        return GL_UNSIGNED_SHORT_5_6_5;
439                 default:
440                         UNREACHABLE(colorbuffer->getInternalFormat());
441                 }
442         }
443
444         return GL_UNSIGNED_BYTE;
445 }
446
447 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
448 {
449         mColorbufferPointer = new Renderbuffer(0, colorbuffer);
450
451         Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
452         mDepthbufferPointer = depthStencilRenderbuffer;
453         mStencilbufferPointer = depthStencilRenderbuffer;
454
455         mColorbufferType = GL_RENDERBUFFER_OES;
456         mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER_OES : GL_NONE_OES;
457         mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER_OES : GL_NONE_OES;
458 }
459
460 }