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
27namespace es2
28{
29
30bool Framebuffer::IsRenderbuffer(GLenum type)
31{
32 return type == GL_RENDERBUFFER || type == GL_FRAMEBUFFER_DEFAULT;
33}
34
35Framebuffer::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
56Framebuffer::~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
66Renderbuffer *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
88void 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
95void 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
102void 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
109void Framebuffer::setReadBuffer(GLenum buf)
110{
111 readBuffer = buf;
112}
113
114void Framebuffer::setDrawBuffer(GLuint index, GLenum buf)
115{
116 drawBuffer[index] = buf;
117}
118
119GLenum Framebuffer::getReadBuffer() const
120{
121 return readBuffer;
122}
123
124GLenum Framebuffer::getDrawBuffer(GLuint index) const
125{
126 return drawBuffer[index];
127}
128
129void 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
153void 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
179egl::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
194egl::Image *Framebuffer::getReadRenderTarget()
195{
196 return getRenderTarget(getReadBufferIndex());
197}
198
199// Increments refcount on surface.
200// caller must Release() the returned surface
201egl::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
215egl::Image *Framebuffer::getStencilBuffer()
216{
217 Renderbuffer *stencilbuffer = mStencilbufferPointer;
218
219 if(stencilbuffer)
220 {
221 return stencilbuffer->getRenderTarget();
222 }
223
224 return nullptr;
225}
226
227Renderbuffer *Framebuffer::getColorbuffer(GLuint index) const
228{
229 return (index < MAX_COLOR_ATTACHMENTS) ? mColorbufferPointer[index] : (Renderbuffer*)nullptr;
230}
231
232Renderbuffer *Framebuffer::getReadColorbuffer() const
233{
234 return getColorbuffer(getReadBufferIndex());
235}
236
237Renderbuffer *Framebuffer::getDepthbuffer() const
238{
239 return mDepthbufferPointer;
240}
241
242Renderbuffer *Framebuffer::getStencilbuffer() const
243{
244 return mStencilbufferPointer;
245}
246
247GLenum Framebuffer::getReadBufferType()
248{
249 if(readBuffer == GL_NONE)
250 {
251 return GL_NONE;
252 }
253
254 return mColorbufferType[getReadBufferIndex()];
255}
256
257GLenum Framebuffer::getColorbufferType(GLuint index)
258{
259 return mColorbufferType[index];
260}
261
262GLenum Framebuffer::getDepthbufferType()
263{
264 return mDepthbufferType;
265}
266
267GLenum Framebuffer::getStencilbufferType()
268{
269 return mStencilbufferType;
270}
271
272GLuint Framebuffer::getColorbufferName(GLuint index)
273{
274 return mColorbufferPointer[index].name();
275}
276
277GLuint Framebuffer::getDepthbufferName()
278{
279 return mDepthbufferPointer.name();
280}
281
282GLuint Framebuffer::getStencilbufferName()
283{
284 return mStencilbufferPointer.name();
285}
286
287GLint Framebuffer::getColorbufferLayer(GLuint index)
288{
289 return mColorbufferLayer[index];
290}
291
292GLint Framebuffer::getDepthbufferLayer()
293{
294 return mDepthbufferLayer;
295}
296
297GLint Framebuffer::getStencilbufferLayer()
298{
299 return mStencilbufferLayer;
300}
301
302bool 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
317GLenum Framebuffer::completeness()
318{
319 int width;
320 int height;
321 int samples;
322
323 return completeness(width, height, samples);
324}
325
326GLenum 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
522GLenum 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_RGB;
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
583GLenum 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
644GLenum 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
658GLenum 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
681GLuint 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
694DefaultFramebuffer::DefaultFramebuffer()
695{
696 readBuffer = GL_BACK;
697 drawBuffer[0] = GL_BACK;
698}
699
700DefaultFramebuffer::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