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 = getContextLocked();
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 for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
333 {
334 if(mColorbufferType[i] != GL_NONE)
335 {
336 Renderbuffer *colorbuffer = getColorbuffer(i);
337
338 if(!colorbuffer)
339 {
340 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
341 }
342
343 if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= mColorbufferLayer[i]))
344 {
345 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
346 }
347
348 if(IsRenderbuffer(mColorbufferType[i]))
349 {
350 if(!IsColorRenderable(colorbuffer->getFormat()))
351 {
352 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
353 }
354 }
355 else if(IsTextureTarget(mColorbufferType[i]))
356 {
357 GLint format = colorbuffer->getFormat();
358
359 if(!IsColorRenderable(format))
360 {
361 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
362 }
363
364 if(IsDepthTexture(format) || IsStencilTexture(format))
365 {
366 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
367 }
368 }
369 else
370 {
371 UNREACHABLE(mColorbufferType[i]);
372 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
373 }
374
375 if(width == -1 || height == -1)
376 {
377 width = colorbuffer->getWidth();
378 height = colorbuffer->getHeight();
379 samples = colorbuffer->getSamples();
380 }
381 else
382 {
383 if(samples != colorbuffer->getSamples())
384 {
385 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
386 }
387
388 width = std::min(width, colorbuffer->getWidth());
389 height = std::min(height, colorbuffer->getHeight());
390 }
391 }
392 }
393
394 Renderbuffer *depthbuffer = nullptr;
395 Renderbuffer *stencilbuffer = nullptr;
396
397 if(mDepthbufferType != GL_NONE)
398 {
399 depthbuffer = getDepthbuffer();
400
401 if(!depthbuffer)
402 {
403 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
404 }
405
406 if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0 || (depthbuffer->getDepth() <= mDepthbufferLayer))
407 {
408 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
409 }
410
411 if(IsRenderbuffer(mDepthbufferType))
412 {
413 if(!es2::IsDepthRenderable(depthbuffer->getFormat()))
414 {
415 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
416 }
417 }
418 else if(IsTextureTarget(mDepthbufferType))
419 {
420 if(!es2::IsDepthTexture(depthbuffer->getFormat()))
421 {
422 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
423 }
424 }
425 else
426 {
427 UNREACHABLE(mDepthbufferType);
428 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
429 }
430
431 if(width == -1 || height == -1)
432 {
433 width = depthbuffer->getWidth();
434 height = depthbuffer->getHeight();
435 samples = depthbuffer->getSamples();
436 }
437 else
438 {
439 if(samples != depthbuffer->getSamples())
440 {
441 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
442 }
443
444 width = std::min(width, depthbuffer->getWidth());
445 height = std::min(height, depthbuffer->getHeight());
446 }
447 }
448
449 if(mStencilbufferType != GL_NONE)
450 {
451 stencilbuffer = getStencilbuffer();
452
453 if(!stencilbuffer)
454 {
455 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
456 }
457
458 if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0 || (stencilbuffer->getDepth() <= mStencilbufferLayer))
459 {
460 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
461 }
462
463 if(IsRenderbuffer(mStencilbufferType))
464 {
465 if(!es2::IsStencilRenderable(stencilbuffer->getFormat()))
466 {
467 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
468 }
469 }
470 else if(IsTextureTarget(mStencilbufferType))
471 {
472 GLenum internalformat = stencilbuffer->getFormat();
473
474 if(!es2::IsStencilTexture(internalformat))
475 {
476 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
477 }
478 }
479 else
480 {
481 UNREACHABLE(mStencilbufferType);
482 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
483 }
484
485 if(width == -1 || height == -1)
486 {
487 width = stencilbuffer->getWidth();
488 height = stencilbuffer->getHeight();
489 samples = stencilbuffer->getSamples();
490 }
491 else
492 {
493 if(samples != stencilbuffer->getSamples())
494 {
495 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
496 }
497
498 width = std::min(width, stencilbuffer->getWidth());
499 height = std::min(height, stencilbuffer->getHeight());
500 }
501 }
502
503 if(depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
504 {
505 // In the GLES 3.0 spec, section 4.4.4, Framebuffer Completeness:
506 // "The framebuffer object target is said to be framebuffer complete if all the following conditions are true:
507 // [...]
508 // Depth and stencil attachments, if present, are the same image.
509 // { FRAMEBUFFER_UNSUPPORTED }"
510 return GL_FRAMEBUFFER_UNSUPPORTED;
511 }
512
513 // We need to have at least one attachment to be complete
514 if(width == -1 || height == -1)
515 {
516 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
517 }
518
519 return GL_FRAMEBUFFER_COMPLETE;
520 }
521
getImplementationColorReadFormat() const522 GLenum Framebuffer::getImplementationColorReadFormat() const
523 {
524 Renderbuffer *colorbuffer = getReadColorbuffer();
525
526 if(colorbuffer)
527 {
528 switch(colorbuffer->getFormat())
529 {
530 case GL_BGRA8_EXT: return GL_BGRA_EXT;
531 case GL_RGBA4: return GL_RGBA;
532 case GL_RGB5_A1: return GL_RGBA;
533 case GL_RGBA8: return GL_RGBA;
534 case GL_RGB565: return GL_RGBA;
535 case GL_RGB8: return GL_RGB;
536 case GL_R8: return GL_RED;
537 case GL_RG8: return GL_RG;
538 case GL_R8I: return GL_RED_INTEGER;
539 case GL_RG8I: return GL_RG_INTEGER;
540 case GL_RGB8I: return GL_RGB_INTEGER;
541 case GL_RGBA8I: return GL_RGBA_INTEGER;
542 case GL_R8UI: return GL_RED_INTEGER;
543 case GL_RG8UI: return GL_RG_INTEGER;
544 case GL_RGB8UI: return GL_RGB_INTEGER;
545 case GL_RGBA8UI: return GL_RGBA_INTEGER;
546 case GL_R16I: return GL_RED_INTEGER;
547 case GL_RG16I: return GL_RG_INTEGER;
548 case GL_RGB16I: return GL_RGB_INTEGER;
549 case GL_RGBA16I: return GL_RGBA_INTEGER;
550 case GL_R16UI: return GL_RED_INTEGER;
551 case GL_RG16UI: return GL_RG_INTEGER;
552 case GL_RGB16UI: return GL_RGB_INTEGER;
553 case GL_RGB10_A2UI: return GL_RGBA_INTEGER;
554 case GL_RGBA16UI: return GL_RGBA_INTEGER;
555 case GL_R32I: return GL_RED_INTEGER;
556 case GL_RG32I: return GL_RG_INTEGER;
557 case GL_RGB32I: return GL_RGB_INTEGER;
558 case GL_RGBA32I: return GL_RGBA_INTEGER;
559 case GL_R32UI: return GL_RED_INTEGER;
560 case GL_RG32UI: return GL_RG_INTEGER;
561 case GL_RGB32UI: return GL_RGB_INTEGER;
562 case GL_RGBA32UI: return GL_RGBA_INTEGER;
563 case GL_R16F: return GL_RED;
564 case GL_RG16F: return GL_RG;
565 case GL_R11F_G11F_B10F: return GL_RGB;
566 case GL_RGB16F: return GL_RGB;
567 case GL_RGBA16F: return GL_RGBA;
568 case GL_R32F: return GL_RED;
569 case GL_RG32F: return GL_RG;
570 case GL_RGB32F: return GL_RGB;
571 case GL_RGBA32F: return GL_RGBA;
572 case GL_RGB10_A2: return GL_RGBA;
573 case GL_SRGB8: return GL_RGB;
574 case GL_SRGB8_ALPHA8: return GL_RGBA;
575 default:
576 UNREACHABLE(colorbuffer->getFormat());
577 }
578 }
579
580 return GL_RGBA;
581 }
582
getImplementationColorReadType() const583 GLenum Framebuffer::getImplementationColorReadType() const
584 {
585 Renderbuffer *colorbuffer = getReadColorbuffer();
586
587 if(colorbuffer)
588 {
589 switch(colorbuffer->getFormat())
590 {
591 case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE;
592 case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
593 case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
594 case GL_RGBA8: return GL_UNSIGNED_BYTE;
595 case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
596 case GL_RGB8: return GL_UNSIGNED_BYTE;
597 case GL_R8: return GL_UNSIGNED_BYTE;
598 case GL_RG8: return GL_UNSIGNED_BYTE;
599 case GL_R8I: return GL_INT;
600 case GL_RG8I: return GL_INT;
601 case GL_RGB8I: return GL_INT;
602 case GL_RGBA8I: return GL_INT;
603 case GL_R8UI: return GL_UNSIGNED_BYTE;
604 case GL_RG8UI: return GL_UNSIGNED_BYTE;
605 case GL_RGB8UI: return GL_UNSIGNED_BYTE;
606 case GL_RGBA8UI: return GL_UNSIGNED_BYTE;
607 case GL_R16I: return GL_INT;
608 case GL_RG16I: return GL_INT;
609 case GL_RGB16I: return GL_INT;
610 case GL_RGBA16I: return GL_INT;
611 case GL_R16UI: return GL_UNSIGNED_INT;
612 case GL_RG16UI: return GL_UNSIGNED_INT;
613 case GL_RGB16UI: return GL_UNSIGNED_INT;
614 case GL_RGB10_A2UI: return GL_UNSIGNED_INT_2_10_10_10_REV;
615 case GL_RGBA16UI: return GL_UNSIGNED_INT;
616 case GL_R32I: return GL_INT;
617 case GL_RG32I: return GL_INT;
618 case GL_RGB32I: return GL_INT;
619 case GL_RGBA32I: return GL_INT;
620 case GL_R32UI: return GL_UNSIGNED_INT;
621 case GL_RG32UI: return GL_UNSIGNED_INT;
622 case GL_RGB32UI: return GL_UNSIGNED_INT;
623 case GL_RGBA32UI: return GL_UNSIGNED_INT;
624 case GL_R16F: return GL_HALF_FLOAT;
625 case GL_RG16F: return GL_HALF_FLOAT;
626 case GL_R11F_G11F_B10F: return GL_HALF_FLOAT;
627 case GL_RGB16F: return GL_HALF_FLOAT;
628 case GL_RGBA16F: return GL_HALF_FLOAT;
629 case GL_R32F: return GL_FLOAT;
630 case GL_RG32F: return GL_FLOAT;
631 case GL_RGB32F: return GL_FLOAT;
632 case GL_RGBA32F: return GL_FLOAT;
633 case GL_RGB10_A2: return GL_UNSIGNED_INT_2_10_10_10_REV;
634 case GL_SRGB8: return GL_UNSIGNED_BYTE;
635 case GL_SRGB8_ALPHA8: return GL_UNSIGNED_BYTE;
636 default:
637 UNREACHABLE(colorbuffer->getFormat());
638 }
639 }
640
641 return GL_UNSIGNED_BYTE;
642 }
643
getDepthReadFormat() const644 GLenum Framebuffer::getDepthReadFormat() const
645 {
646 Renderbuffer *depthbuffer = getDepthbuffer();
647
648 if(depthbuffer)
649 {
650 // There is only one depth read format.
651 return GL_DEPTH_COMPONENT;
652 }
653
654 // If there is no depth buffer, GL_INVALID_OPERATION occurs.
655 return GL_NONE;
656 }
657
getDepthReadType() const658 GLenum Framebuffer::getDepthReadType() const
659 {
660 Renderbuffer *depthbuffer = getDepthbuffer();
661
662 if(depthbuffer)
663 {
664 switch(depthbuffer->getFormat())
665 {
666 case GL_DEPTH_COMPONENT16: return GL_UNSIGNED_SHORT;
667 case GL_DEPTH_COMPONENT24: return GL_UNSIGNED_INT;
668 case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT;
669 case GL_DEPTH_COMPONENT32F: return GL_FLOAT;
670 case GL_DEPTH24_STENCIL8: return GL_UNSIGNED_INT_24_8_OES;
671 case GL_DEPTH32F_STENCIL8: return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
672 default:
673 UNREACHABLE(depthbuffer->getFormat());
674 }
675 }
676
677 // If there is no depth buffer, GL_INVALID_OPERATION occurs.
678 return GL_NONE;
679 }
680
getReadBufferIndex() const681 GLuint Framebuffer::getReadBufferIndex() const
682 {
683 switch(readBuffer)
684 {
685 case GL_BACK:
686 return 0;
687 case GL_NONE:
688 return GL_INVALID_INDEX;
689 default:
690 return readBuffer - GL_COLOR_ATTACHMENT0;
691 }
692 }
693
DefaultFramebuffer()694 DefaultFramebuffer::DefaultFramebuffer()
695 {
696 readBuffer = GL_BACK;
697 drawBuffer[0] = GL_BACK;
698 }
699
DefaultFramebuffer(Colorbuffer * colorbuffer,DepthStencilbuffer * depthStencil)700 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
701 {
702 GLenum defaultRenderbufferType = GL_FRAMEBUFFER_DEFAULT;
703 mColorbufferPointer[0] = new Renderbuffer(0, colorbuffer);
704 mColorbufferType[0] = defaultRenderbufferType;
705
706 readBuffer = GL_BACK;
707 drawBuffer[0] = GL_BACK;
708 for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++)
709 {
710 mColorbufferPointer[i] = nullptr;
711 mColorbufferType[i] = GL_NONE;
712 }
713
714 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
715 mDepthbufferPointer = depthStencilRenderbuffer;
716 mStencilbufferPointer = depthStencilRenderbuffer;
717
718 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_FRAMEBUFFER_DEFAULT : GL_NONE;
719 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_FRAMEBUFFER_DEFAULT : GL_NONE;
720 }
721
722 }
723