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 #include <algorithm>
26
27 namespace es2
28 {
29
IsRenderbuffer(GLenum type)30 bool Framebuffer::IsRenderbuffer(GLenum type)
31 {
32 return type == GL_RENDERBUFFER || type == GL_FRAMEBUFFER_DEFAULT;
33 }
34
Framebuffer()35 Framebuffer::Framebuffer()
36 {
37 readBuffer = GL_COLOR_ATTACHMENT0;
38 drawBuffer[0] = GL_COLOR_ATTACHMENT0;
39 for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++)
40 {
41 drawBuffer[i] = GL_NONE;
42 }
43
44 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
45 {
46 mColorbufferType[i] = GL_NONE;
47 mColorbufferLayer[i] = 0;
48 }
49
50 mDepthbufferType = GL_NONE;
51 mDepthbufferLayer = 0;
52 mStencilbufferType = GL_NONE;
53 mStencilbufferLayer = 0;
54 }
55
~Framebuffer()56 Framebuffer::~Framebuffer()
57 {
58 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
59 {
60 mColorbufferPointer[i] = nullptr;
61 }
62 mDepthbufferPointer = nullptr;
63 mStencilbufferPointer = nullptr;
64 }
65
lookupRenderbuffer(GLenum type,GLuint handle,GLint level) const66 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const
67 {
68 Context *context = getContext();
69 Renderbuffer *buffer = nullptr;
70
71 if(type == GL_NONE)
72 {
73 buffer = nullptr;
74 }
75 else if(IsRenderbuffer(type))
76 {
77 buffer = context->getRenderbuffer(handle);
78 }
79 else if(IsTextureTarget(type))
80 {
81 buffer = context->getTexture(handle)->getRenderbuffer(type, level);
82 }
83 else UNREACHABLE(type);
84
85 return buffer;
86 }
87
setColorbuffer(GLenum type,GLuint colorbuffer,GLuint index,GLint level,GLint layer)88 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index, GLint level, GLint layer)
89 {
90 mColorbufferType[index] = (colorbuffer != 0) ? type : GL_NONE;
91 mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer, level);
92 mColorbufferLayer[index] = layer;
93 }
94
setDepthbuffer(GLenum type,GLuint depthbuffer,GLint level,GLint layer)95 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
96 {
97 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
98 mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level);
99 mDepthbufferLayer = layer;
100 }
101
setStencilbuffer(GLenum type,GLuint stencilbuffer,GLint level,GLint layer)102 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
103 {
104 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
105 mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level);
106 mStencilbufferLayer = layer;
107 }
108
setReadBuffer(GLenum buf)109 void Framebuffer::setReadBuffer(GLenum buf)
110 {
111 readBuffer = buf;
112 }
113
setDrawBuffer(GLuint index,GLenum buf)114 void Framebuffer::setDrawBuffer(GLuint index, GLenum buf)
115 {
116 drawBuffer[index] = buf;
117 }
118
getReadBuffer() const119 GLenum Framebuffer::getReadBuffer() const
120 {
121 return readBuffer;
122 }
123
getDrawBuffer(GLuint index) const124 GLenum Framebuffer::getDrawBuffer(GLuint index) const
125 {
126 return drawBuffer[index];
127 }
128
detachTexture(GLuint texture)129 void Framebuffer::detachTexture(GLuint texture)
130 {
131 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
132 {
133 if(mColorbufferPointer[i].name() == texture && IsTextureTarget(mColorbufferType[i]))
134 {
135 mColorbufferType[i] = GL_NONE;
136 mColorbufferPointer[i] = nullptr;
137 }
138 }
139
140 if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType))
141 {
142 mDepthbufferType = GL_NONE;
143 mDepthbufferPointer = nullptr;
144 }
145
146 if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType))
147 {
148 mStencilbufferType = GL_NONE;
149 mStencilbufferPointer = nullptr;
150 }
151 }
152
detachRenderbuffer(GLuint renderbuffer)153 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
154 {
155 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
156 {
157 if(mColorbufferPointer[i].name() == renderbuffer && IsRenderbuffer(mColorbufferType[i]))
158 {
159 mColorbufferType[i] = GL_NONE;
160 mColorbufferPointer[i] = nullptr;
161 }
162 }
163
164 if(mDepthbufferPointer.name() == renderbuffer && IsRenderbuffer(mDepthbufferType))
165 {
166 mDepthbufferType = GL_NONE;
167 mDepthbufferPointer = nullptr;
168 }
169
170 if(mStencilbufferPointer.name() == renderbuffer && IsRenderbuffer(mStencilbufferType))
171 {
172 mStencilbufferType = GL_NONE;
173 mStencilbufferPointer = nullptr;
174 }
175 }
176
177 // Increments refcount on surface.
178 // caller must Release() the returned surface
getRenderTarget(GLuint index)179 egl::Image *Framebuffer::getRenderTarget(GLuint index)
180 {
181 if(index < MAX_COLOR_ATTACHMENTS)
182 {
183 Renderbuffer *colorbuffer = mColorbufferPointer[index];
184
185 if(colorbuffer)
186 {
187 return colorbuffer->getRenderTarget();
188 }
189 }
190
191 return nullptr;
192 }
193
getReadRenderTarget()194 egl::Image *Framebuffer::getReadRenderTarget()
195 {
196 return getRenderTarget(getReadBufferIndex());
197 }
198
199 // Increments refcount on surface.
200 // caller must Release() the returned surface
getDepthBuffer()201 egl::Image *Framebuffer::getDepthBuffer()
202 {
203 Renderbuffer *depthbuffer = mDepthbufferPointer;
204
205 if(depthbuffer)
206 {
207 return depthbuffer->getRenderTarget();
208 }
209
210 return nullptr;
211 }
212
213 // Increments refcount on surface.
214 // caller must Release() the returned surface
getStencilBuffer()215 egl::Image *Framebuffer::getStencilBuffer()
216 {
217 Renderbuffer *stencilbuffer = mStencilbufferPointer;
218
219 if(stencilbuffer)
220 {
221 return stencilbuffer->getRenderTarget();
222 }
223
224 return nullptr;
225 }
226
getColorbuffer(GLuint index) const227 Renderbuffer *Framebuffer::getColorbuffer(GLuint index) const
228 {
229 return (index < MAX_COLOR_ATTACHMENTS) ? mColorbufferPointer[index] : (Renderbuffer*)nullptr;
230 }
231
getReadColorbuffer() const232 Renderbuffer *Framebuffer::getReadColorbuffer() const
233 {
234 return getColorbuffer(getReadBufferIndex());
235 }
236
getDepthbuffer() const237 Renderbuffer *Framebuffer::getDepthbuffer() const
238 {
239 return mDepthbufferPointer;
240 }
241
getStencilbuffer() const242 Renderbuffer *Framebuffer::getStencilbuffer() const
243 {
244 return mStencilbufferPointer;
245 }
246
getReadBufferType()247 GLenum Framebuffer::getReadBufferType()
248 {
249 if(readBuffer == GL_NONE)
250 {
251 return GL_NONE;
252 }
253
254 return mColorbufferType[getReadBufferIndex()];
255 }
256
getColorbufferType(GLuint index)257 GLenum Framebuffer::getColorbufferType(GLuint index)
258 {
259 return mColorbufferType[index];
260 }
261
getDepthbufferType()262 GLenum Framebuffer::getDepthbufferType()
263 {
264 return mDepthbufferType;
265 }
266
getStencilbufferType()267 GLenum Framebuffer::getStencilbufferType()
268 {
269 return mStencilbufferType;
270 }
271
getColorbufferName(GLuint index)272 GLuint Framebuffer::getColorbufferName(GLuint index)
273 {
274 return mColorbufferPointer[index].name();
275 }
276
getDepthbufferName()277 GLuint Framebuffer::getDepthbufferName()
278 {
279 return mDepthbufferPointer.name();
280 }
281
getStencilbufferName()282 GLuint Framebuffer::getStencilbufferName()
283 {
284 return mStencilbufferPointer.name();
285 }
286
getColorbufferLayer(GLuint index)287 GLint Framebuffer::getColorbufferLayer(GLuint index)
288 {
289 return mColorbufferLayer[index];
290 }
291
getDepthbufferLayer()292 GLint Framebuffer::getDepthbufferLayer()
293 {
294 return mDepthbufferLayer;
295 }
296
getStencilbufferLayer()297 GLint Framebuffer::getStencilbufferLayer()
298 {
299 return mStencilbufferLayer;
300 }
301
hasStencil()302 bool Framebuffer::hasStencil()
303 {
304 if(mStencilbufferType != GL_NONE)
305 {
306 Renderbuffer *stencilbufferObject = getStencilbuffer();
307
308 if(stencilbufferObject)
309 {
310 return stencilbufferObject->getStencilSize() > 0;
311 }
312 }
313
314 return false;
315 }
316
completeness()317 GLenum Framebuffer::completeness()
318 {
319 int width;
320 int height;
321 int samples;
322
323 return completeness(width, height, samples);
324 }
325
completeness(int & width,int & height,int & samples)326 GLenum Framebuffer::completeness(int &width, int &height, int &samples)
327 {
328 width = -1;
329 height = -1;
330 samples = -1;
331
332 GLint version = egl::getClientVersion();
333
334 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
335 {
336 if(mColorbufferType[i] != GL_NONE)
337 {
338 Renderbuffer *colorbuffer = getColorbuffer(i);
339
340 if(!colorbuffer)
341 {
342 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
343 }
344
345 if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= mColorbufferLayer[i]))
346 {
347 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
348 }
349
350 if(IsRenderbuffer(mColorbufferType[i]))
351 {
352 if(!IsColorRenderable(colorbuffer->getFormat(), version))
353 {
354 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
355 }
356 }
357 else if(IsTextureTarget(mColorbufferType[i]))
358 {
359 GLenum format = colorbuffer->getFormat();
360
361 if(!IsColorRenderable(format, version))
362 {
363 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
364 }
365
366 if(IsDepthTexture(format) || IsStencilTexture(format))
367 {
368 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
369 }
370 }
371 else
372 {
373 UNREACHABLE(mColorbufferType[i]);
374 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
375 }
376
377 if(width == -1 || height == -1)
378 {
379 width = colorbuffer->getWidth();
380 height = colorbuffer->getHeight();
381 samples = colorbuffer->getSamples();
382 }
383 else
384 {
385 if(version < 3 && (width != colorbuffer->getWidth() || height != colorbuffer->getHeight()))
386 {
387 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
388 }
389
390 if(samples != colorbuffer->getSamples())
391 {
392 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
393 }
394
395 width = std::min(width, colorbuffer->getWidth());
396 height = std::min(height, colorbuffer->getHeight());
397 }
398 }
399 }
400
401 Renderbuffer *depthbuffer = nullptr;
402 Renderbuffer *stencilbuffer = nullptr;
403
404 if(mDepthbufferType != GL_NONE)
405 {
406 depthbuffer = getDepthbuffer();
407
408 if(!depthbuffer)
409 {
410 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
411 }
412
413 if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0 || (depthbuffer->getDepth() <= mDepthbufferLayer))
414 {
415 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
416 }
417
418 if(IsRenderbuffer(mDepthbufferType))
419 {
420 if(!es2::IsDepthRenderable(depthbuffer->getFormat(), version))
421 {
422 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
423 }
424 }
425 else if(IsTextureTarget(mDepthbufferType))
426 {
427 if(!es2::IsDepthTexture(depthbuffer->getFormat()))
428 {
429 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
430 }
431 }
432 else
433 {
434 UNREACHABLE(mDepthbufferType);
435 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
436 }
437
438 if(width == -1 || height == -1)
439 {
440 width = depthbuffer->getWidth();
441 height = depthbuffer->getHeight();
442 samples = depthbuffer->getSamples();
443 }
444 else
445 {
446 if(version < 3 && (width != depthbuffer->getWidth() || height != depthbuffer->getHeight()))
447 {
448 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
449 }
450
451 if(samples != depthbuffer->getSamples())
452 {
453 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
454 }
455
456 width = std::min(width, depthbuffer->getWidth());
457 height = std::min(height, depthbuffer->getHeight());
458 }
459 }
460
461 if(mStencilbufferType != GL_NONE)
462 {
463 stencilbuffer = getStencilbuffer();
464
465 if(!stencilbuffer)
466 {
467 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
468 }
469
470 if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0 || (stencilbuffer->getDepth() <= mStencilbufferLayer))
471 {
472 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
473 }
474
475 if(IsRenderbuffer(mStencilbufferType))
476 {
477 if(!es2::IsStencilRenderable(stencilbuffer->getFormat(), version))
478 {
479 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
480 }
481 }
482 else if(IsTextureTarget(mStencilbufferType))
483 {
484 GLenum internalformat = stencilbuffer->getFormat();
485
486 if(!es2::IsStencilTexture(internalformat))
487 {
488 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
489 }
490 }
491 else
492 {
493 UNREACHABLE(mStencilbufferType);
494 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
495 }
496
497 if(width == -1 || height == -1)
498 {
499 width = stencilbuffer->getWidth();
500 height = stencilbuffer->getHeight();
501 samples = stencilbuffer->getSamples();
502 }
503 else
504 {
505 if(version < 3 && (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight()))
506 {
507 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
508 }
509
510 if(samples != stencilbuffer->getSamples())
511 {
512 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
513 }
514
515 width = std::min(width, stencilbuffer->getWidth());
516 height = std::min(height, stencilbuffer->getHeight());
517 }
518 }
519
520 if((version >= 3) && depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
521 {
522 // In the GLES 3.0 spec, section 4.4.4, Framebuffer Completeness:
523 // "The framebuffer object target is said to be framebuffer complete if all the following conditions are true:
524 // [...]
525 // Depth and stencil attachments, if present, are the same image.
526 // { FRAMEBUFFER_UNSUPPORTED }"
527 return GL_FRAMEBUFFER_UNSUPPORTED;
528 }
529
530 // We need to have at least one attachment to be complete
531 if(width == -1 || height == -1)
532 {
533 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
534 }
535
536 return GL_FRAMEBUFFER_COMPLETE;
537 }
538
getImplementationColorReadFormat() const539 GLenum Framebuffer::getImplementationColorReadFormat() const
540 {
541 Renderbuffer *colorbuffer = getReadColorbuffer();
542
543 if(colorbuffer)
544 {
545 switch(colorbuffer->getFormat())
546 {
547 case GL_BGRA8_EXT: return GL_BGRA_EXT;
548 case GL_RGBA4: return GL_RGBA;
549 case GL_RGB5_A1: return GL_RGBA;
550 case GL_RGBA8: return GL_RGBA;
551 case GL_RGB565: return GL_RGBA;
552 case GL_RGB8: return GL_RGB;
553 case GL_R8: return GL_RED;
554 case GL_RG8: return GL_RG;
555 case GL_R8I: return GL_RED_INTEGER;
556 case GL_RG8I: return GL_RG_INTEGER;
557 case GL_RGB8I: return GL_RGB_INTEGER;
558 case GL_RGBA8I: return GL_RGBA_INTEGER;
559 case GL_R8UI: return GL_RED_INTEGER;
560 case GL_RG8UI: return GL_RG_INTEGER;
561 case GL_RGB8UI: return GL_RGB_INTEGER;
562 case GL_RGBA8UI: return GL_RGBA_INTEGER;
563 case GL_R16I: return GL_RED_INTEGER;
564 case GL_RG16I: return GL_RG_INTEGER;
565 case GL_RGB16I: return GL_RGB_INTEGER;
566 case GL_RGBA16I: return GL_RGBA_INTEGER;
567 case GL_R16UI: return GL_RED_INTEGER;
568 case GL_RG16UI: return GL_RG_INTEGER;
569 case GL_RGB16UI: return GL_RGB_INTEGER;
570 case GL_RGB10_A2UI: return GL_RGBA_INTEGER;
571 case GL_RGBA16UI: return GL_RGBA_INTEGER;
572 case GL_R32I: return GL_RED_INTEGER;
573 case GL_RG32I: return GL_RG_INTEGER;
574 case GL_RGB32I: return GL_RGB_INTEGER;
575 case GL_RGBA32I: return GL_RGBA_INTEGER;
576 case GL_R32UI: return GL_RED_INTEGER;
577 case GL_RG32UI: return GL_RG_INTEGER;
578 case GL_RGB32UI: return GL_RGB_INTEGER;
579 case GL_RGBA32UI: return GL_RGBA_INTEGER;
580 case GL_R16F: return GL_RED;
581 case GL_RG16F: return GL_RG;
582 case GL_R11F_G11F_B10F: return GL_RGB;
583 case GL_RGB16F: return GL_RGB;
584 case GL_RGBA16F: return GL_RGBA;
585 case GL_R32F: return GL_RED;
586 case GL_RG32F: return GL_RG;
587 case GL_RGB32F: return GL_RGB;
588 case GL_RGBA32F: return GL_RGBA;
589 case GL_RGB10_A2: return GL_RGBA;
590 case GL_SRGB8: return GL_RGB;
591 case GL_SRGB8_ALPHA8: return GL_RGBA;
592 default:
593 UNREACHABLE(colorbuffer->getFormat());
594 }
595 }
596
597 return GL_RGBA;
598 }
599
getImplementationColorReadType() const600 GLenum Framebuffer::getImplementationColorReadType() const
601 {
602 Renderbuffer *colorbuffer = getReadColorbuffer();
603
604 if(colorbuffer)
605 {
606 switch(colorbuffer->getFormat())
607 {
608 case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE;
609 case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
610 case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
611 case GL_RGBA8: return GL_UNSIGNED_BYTE;
612 case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
613 case GL_RGB8: return GL_UNSIGNED_BYTE;
614 case GL_R8: return GL_UNSIGNED_BYTE;
615 case GL_RG8: return GL_UNSIGNED_BYTE;
616 case GL_R8I: return GL_INT;
617 case GL_RG8I: return GL_INT;
618 case GL_RGB8I: return GL_INT;
619 case GL_RGBA8I: return GL_INT;
620 case GL_R8UI: return GL_UNSIGNED_BYTE;
621 case GL_RG8UI: return GL_UNSIGNED_BYTE;
622 case GL_RGB8UI: return GL_UNSIGNED_BYTE;
623 case GL_RGBA8UI: return GL_UNSIGNED_BYTE;
624 case GL_R16I: return GL_INT;
625 case GL_RG16I: return GL_INT;
626 case GL_RGB16I: return GL_INT;
627 case GL_RGBA16I: return GL_INT;
628 case GL_R16UI: return GL_UNSIGNED_INT;
629 case GL_RG16UI: return GL_UNSIGNED_INT;
630 case GL_RGB16UI: return GL_UNSIGNED_INT;
631 case GL_RGB10_A2UI: return GL_UNSIGNED_INT_2_10_10_10_REV;
632 case GL_RGBA16UI: return GL_UNSIGNED_INT;
633 case GL_R32I: return GL_INT;
634 case GL_RG32I: return GL_INT;
635 case GL_RGB32I: return GL_INT;
636 case GL_RGBA32I: return GL_INT;
637 case GL_R32UI: return GL_UNSIGNED_INT;
638 case GL_RG32UI: return GL_UNSIGNED_INT;
639 case GL_RGB32UI: return GL_UNSIGNED_INT;
640 case GL_RGBA32UI: return GL_UNSIGNED_INT;
641 case GL_R16F: return GL_FLOAT;
642 case GL_RG16F: return GL_FLOAT;
643 case GL_R11F_G11F_B10F: return GL_FLOAT;
644 case GL_RGB16F: return GL_FLOAT;
645 case GL_RGBA16F: return GL_FLOAT;
646 case GL_R32F: return GL_FLOAT;
647 case GL_RG32F: return GL_FLOAT;
648 case GL_RGB32F: return GL_FLOAT;
649 case GL_RGBA32F: return GL_FLOAT;
650 case GL_RGB10_A2: return GL_UNSIGNED_INT_2_10_10_10_REV;
651 case GL_SRGB8: return GL_UNSIGNED_BYTE;
652 case GL_SRGB8_ALPHA8: return GL_UNSIGNED_BYTE;
653 default:
654 UNREACHABLE(colorbuffer->getFormat());
655 }
656 }
657
658 return GL_UNSIGNED_BYTE;
659 }
660
getDepthReadFormat() const661 GLenum Framebuffer::getDepthReadFormat() const
662 {
663 Renderbuffer *depthbuffer = getDepthbuffer();
664
665 if(depthbuffer)
666 {
667 // There is only one depth read format.
668 return GL_DEPTH_COMPONENT;
669 }
670
671 // If there is no depth buffer, GL_INVALID_OPERATION occurs.
672 return GL_NONE;
673 }
674
getDepthReadType() const675 GLenum Framebuffer::getDepthReadType() const
676 {
677 Renderbuffer *depthbuffer = getDepthbuffer();
678
679 if(depthbuffer)
680 {
681 switch(depthbuffer->getFormat())
682 {
683 case GL_DEPTH_COMPONENT16: return GL_UNSIGNED_SHORT;
684 case GL_DEPTH_COMPONENT24: return GL_UNSIGNED_INT;
685 case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT;
686 case GL_DEPTH_COMPONENT32F: return GL_FLOAT;
687 case GL_DEPTH24_STENCIL8: return GL_UNSIGNED_INT_24_8_OES;
688 case GL_DEPTH32F_STENCIL8: return GL_FLOAT;
689 default:
690 UNREACHABLE(depthbuffer->getFormat());
691 }
692 }
693
694 // If there is no depth buffer, GL_INVALID_OPERATION occurs.
695 return GL_NONE;
696 }
697
getReadBufferIndex() const698 GLuint Framebuffer::getReadBufferIndex() const
699 {
700 switch(readBuffer)
701 {
702 case GL_BACK:
703 return 0;
704 case GL_NONE:
705 return GL_INVALID_INDEX;
706 default:
707 return readBuffer - GL_COLOR_ATTACHMENT0;
708 }
709 }
710
DefaultFramebuffer()711 DefaultFramebuffer::DefaultFramebuffer()
712 {
713 readBuffer = GL_BACK;
714 drawBuffer[0] = GL_BACK;
715 }
716
DefaultFramebuffer(Colorbuffer * colorbuffer,DepthStencilbuffer * depthStencil)717 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
718 {
719 GLenum defaultRenderbufferType = egl::getClientVersion() < 3 ? GL_RENDERBUFFER : GL_FRAMEBUFFER_DEFAULT;
720 mColorbufferPointer[0] = new Renderbuffer(0, colorbuffer);
721 mColorbufferType[0] = defaultRenderbufferType;
722
723 readBuffer = GL_BACK;
724 drawBuffer[0] = GL_BACK;
725 for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++)
726 {
727 mColorbufferPointer[i] = nullptr;
728 mColorbufferType[i] = GL_NONE;
729 }
730
731 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
732 mDepthbufferPointer = depthStencilRenderbuffer;
733 mStencilbufferPointer = depthStencilRenderbuffer;
734
735 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? defaultRenderbufferType : GL_NONE;
736 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? defaultRenderbufferType : GL_NONE;
737 }
738
739 }
740