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 // Renderbuffer.cpp: the Renderbuffer class and its derived classes
16 // Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
17 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
18
19 #include "Renderbuffer.h"
20
21 #include "main.h"
22 #include "Texture.h"
23 #include "utilities.h"
24
25 namespace es2
26 {
RenderbufferInterface()27 RenderbufferInterface::RenderbufferInterface()
28 {
29 }
30
31 // The default case for classes inherited from RenderbufferInterface is not to
32 // need to do anything upon the reference count to the parent Renderbuffer incrementing
33 // or decrementing.
addProxyRef(const Renderbuffer * proxy)34 void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy)
35 {
36 }
37
releaseProxy(const Renderbuffer * proxy)38 void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy)
39 {
40 }
41
getRedSize() const42 GLuint RenderbufferInterface::getRedSize() const
43 {
44 return GetRedSize(getFormat());
45 }
46
getGreenSize() const47 GLuint RenderbufferInterface::getGreenSize() const
48 {
49 return GetGreenSize(getFormat());
50 }
51
getBlueSize() const52 GLuint RenderbufferInterface::getBlueSize() const
53 {
54 return GetBlueSize(getFormat());
55 }
56
getAlphaSize() const57 GLuint RenderbufferInterface::getAlphaSize() const
58 {
59 return GetAlphaSize(getFormat());
60 }
61
getDepthSize() const62 GLuint RenderbufferInterface::getDepthSize() const
63 {
64 return GetDepthSize(getFormat());
65 }
66
getStencilSize() const67 GLuint RenderbufferInterface::getStencilSize() const
68 {
69 return GetStencilSize(getFormat());
70 }
71
72 ///// RenderbufferTexture2D Implementation ////////
73
RenderbufferTexture2D(Texture2D * texture,GLint level)74 RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : mLevel(level)
75 {
76 mTexture2D = texture;
77 }
78
~RenderbufferTexture2D()79 RenderbufferTexture2D::~RenderbufferTexture2D()
80 {
81 mTexture2D = nullptr;
82 }
83
84 // Textures need to maintain their own reference count for references via
85 // Renderbuffers acting as proxies. Here, we notify the texture of a reference.
addProxyRef(const Renderbuffer * proxy)86 void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy)
87 {
88 mTexture2D->addProxyRef(proxy);
89 }
90
releaseProxy(const Renderbuffer * proxy)91 void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy)
92 {
93 mTexture2D->releaseProxy(proxy);
94 }
95
96 // Increments refcount on image.
97 // caller must release() the returned image
getRenderTarget()98 egl::Image *RenderbufferTexture2D::getRenderTarget()
99 {
100 return mTexture2D->getRenderTarget(GL_TEXTURE_2D, mLevel);
101 }
102
103 // Increments refcount on image.
104 // caller must release() the returned image
createSharedImage()105 egl::Image *RenderbufferTexture2D::createSharedImage()
106 {
107 return mTexture2D->createSharedImage(GL_TEXTURE_2D, mLevel);
108 }
109
isShared() const110 bool RenderbufferTexture2D::isShared() const
111 {
112 return mTexture2D->isShared(GL_TEXTURE_2D, mLevel);
113 }
114
getWidth() const115 GLsizei RenderbufferTexture2D::getWidth() const
116 {
117 return mTexture2D->getWidth(GL_TEXTURE_2D, mLevel);
118 }
119
getHeight() const120 GLsizei RenderbufferTexture2D::getHeight() const
121 {
122 return mTexture2D->getHeight(GL_TEXTURE_2D, mLevel);
123 }
124
getFormat() const125 GLint RenderbufferTexture2D::getFormat() const
126 {
127 return mTexture2D->getFormat(GL_TEXTURE_2D, mLevel);
128 }
129
getSamples() const130 GLsizei RenderbufferTexture2D::getSamples() const
131 {
132 return 0; // Core OpenGL ES 3.0 does not support multisample textures.
133 }
134
135 ///// RenderbufferTexture2DRect Implementation ////////
136
RenderbufferTexture2DRect(Texture2DRect * texture)137 RenderbufferTexture2DRect::RenderbufferTexture2DRect(Texture2DRect *texture)
138 {
139 mTexture2DRect = texture;
140 }
141
~RenderbufferTexture2DRect()142 RenderbufferTexture2DRect::~RenderbufferTexture2DRect()
143 {
144 mTexture2DRect = NULL;
145 }
146
147 // Textures need to maintain their own reference count for references via
148 // Renderbuffers acting as proxies. Here, we notify the texture of a reference.
addProxyRef(const Renderbuffer * proxy)149 void RenderbufferTexture2DRect::addProxyRef(const Renderbuffer *proxy)
150 {
151 mTexture2DRect->addProxyRef(proxy);
152 }
153
releaseProxy(const Renderbuffer * proxy)154 void RenderbufferTexture2DRect::releaseProxy(const Renderbuffer *proxy)
155 {
156 mTexture2DRect->releaseProxy(proxy);
157 }
158
159 // Increments refcount on image.
160 // caller must release() the returned image
getRenderTarget()161 egl::Image *RenderbufferTexture2DRect::getRenderTarget()
162 {
163 return mTexture2DRect->getRenderTarget(GL_TEXTURE_RECTANGLE_ARB, 0);
164 }
165
166 // Increments refcount on image.
167 // caller must release() the returned image
createSharedImage()168 egl::Image *RenderbufferTexture2DRect::createSharedImage()
169 {
170 return mTexture2DRect->createSharedImage(GL_TEXTURE_RECTANGLE_ARB, 0);
171 }
172
isShared() const173 bool RenderbufferTexture2DRect::isShared() const
174 {
175 return mTexture2DRect->isShared(GL_TEXTURE_RECTANGLE_ARB, 0);
176 }
177
getWidth() const178 GLsizei RenderbufferTexture2DRect::getWidth() const
179 {
180 return mTexture2DRect->getWidth(GL_TEXTURE_RECTANGLE_ARB, 0);
181 }
182
getHeight() const183 GLsizei RenderbufferTexture2DRect::getHeight() const
184 {
185 return mTexture2DRect->getHeight(GL_TEXTURE_RECTANGLE_ARB, 0);
186 }
187
getFormat() const188 GLint RenderbufferTexture2DRect::getFormat() const
189 {
190 return mTexture2DRect->getFormat(GL_TEXTURE_RECTANGLE_ARB, 0);
191 }
192
getSamples() const193 GLsizei RenderbufferTexture2DRect::getSamples() const
194 {
195 return 0; // Core OpenGL ES 3.0 does not support multisample textures.
196 }
197
198 ///// RenderbufferTexture3D Implementation ////////
199
RenderbufferTexture3D(Texture3D * texture,GLint level)200 RenderbufferTexture3D::RenderbufferTexture3D(Texture3D *texture, GLint level) : mLevel(level)
201 {
202 mTexture3D = texture;
203 }
204
~RenderbufferTexture3D()205 RenderbufferTexture3D::~RenderbufferTexture3D()
206 {
207 mTexture3D = NULL;
208 }
209
210 // Textures need to maintain their own reference count for references via
211 // Renderbuffers acting as proxies. Here, we notify the texture of a reference.
addProxyRef(const Renderbuffer * proxy)212 void RenderbufferTexture3D::addProxyRef(const Renderbuffer *proxy)
213 {
214 mTexture3D->addProxyRef(proxy);
215 }
216
releaseProxy(const Renderbuffer * proxy)217 void RenderbufferTexture3D::releaseProxy(const Renderbuffer *proxy)
218 {
219 mTexture3D->releaseProxy(proxy);
220 }
221
222 // Increments refcount on image.
223 // caller must release() the returned image
getRenderTarget()224 egl::Image *RenderbufferTexture3D::getRenderTarget()
225 {
226 return mTexture3D->getRenderTarget(mTexture3D->getTarget(), mLevel);
227 }
228
229 // Increments refcount on image.
230 // caller must release() the returned image
createSharedImage()231 egl::Image *RenderbufferTexture3D::createSharedImage()
232 {
233 return mTexture3D->createSharedImage(mTexture3D->getTarget(), mLevel);
234 }
235
isShared() const236 bool RenderbufferTexture3D::isShared() const
237 {
238 return mTexture3D->isShared(mTexture3D->getTarget(), mLevel);
239 }
240
getWidth() const241 GLsizei RenderbufferTexture3D::getWidth() const
242 {
243 return mTexture3D->getWidth(mTexture3D->getTarget(), mLevel);
244 }
245
getHeight() const246 GLsizei RenderbufferTexture3D::getHeight() const
247 {
248 return mTexture3D->getHeight(mTexture3D->getTarget(), mLevel);
249 }
250
getDepth() const251 GLsizei RenderbufferTexture3D::getDepth() const
252 {
253 return mTexture3D->getDepth(mTexture3D->getTarget(), mLevel);
254 }
255
getFormat() const256 GLint RenderbufferTexture3D::getFormat() const
257 {
258 return mTexture3D->getFormat(mTexture3D->getTarget(), mLevel);
259 }
260
getSamples() const261 GLsizei RenderbufferTexture3D::getSamples() const
262 {
263 return 0; // Core OpenGL ES 3.0 does not support multisample textures.
264 }
265
266 ///// RenderbufferTextureCubeMap Implementation ////////
267
RenderbufferTextureCubeMap(TextureCubeMap * texture,GLenum target,GLint level)268 RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target, GLint level) : mTarget(target), mLevel(level)
269 {
270 mTextureCubeMap = texture;
271 }
272
~RenderbufferTextureCubeMap()273 RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap()
274 {
275 mTextureCubeMap = NULL;
276 }
277
278 // Textures need to maintain their own reference count for references via
279 // Renderbuffers acting as proxies. Here, we notify the texture of a reference.
addProxyRef(const Renderbuffer * proxy)280 void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy)
281 {
282 mTextureCubeMap->addProxyRef(proxy);
283 }
284
releaseProxy(const Renderbuffer * proxy)285 void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy)
286 {
287 mTextureCubeMap->releaseProxy(proxy);
288 }
289
290 // Increments refcount on image.
291 // caller must release() the returned image
getRenderTarget()292 egl::Image *RenderbufferTextureCubeMap::getRenderTarget()
293 {
294 return mTextureCubeMap->getRenderTarget(mTarget, mLevel);
295 }
296
297 // Increments refcount on image.
298 // caller must release() the returned image
createSharedImage()299 egl::Image *RenderbufferTextureCubeMap::createSharedImage()
300 {
301 return mTextureCubeMap->createSharedImage(mTarget, mLevel);
302 }
303
isShared() const304 bool RenderbufferTextureCubeMap::isShared() const
305 {
306 return mTextureCubeMap->isShared(mTarget, mLevel);
307 }
308
getWidth() const309 GLsizei RenderbufferTextureCubeMap::getWidth() const
310 {
311 return mTextureCubeMap->getWidth(mTarget, mLevel);
312 }
313
getHeight() const314 GLsizei RenderbufferTextureCubeMap::getHeight() const
315 {
316 return mTextureCubeMap->getHeight(mTarget, mLevel);
317 }
318
getFormat() const319 GLint RenderbufferTextureCubeMap::getFormat() const
320 {
321 return mTextureCubeMap->getFormat(mTarget, mLevel);
322 }
323
getSamples() const324 GLsizei RenderbufferTextureCubeMap::getSamples() const
325 {
326 return 0; // Core OpenGL ES 3.0 does not support multisample textures.
327 }
328
329 ////// Renderbuffer Implementation //////
330
Renderbuffer(GLuint name,RenderbufferInterface * instance)331 Renderbuffer::Renderbuffer(GLuint name, RenderbufferInterface *instance) : NamedObject(name)
332 {
333 ASSERT(instance);
334 mInstance = instance;
335 }
336
~Renderbuffer()337 Renderbuffer::~Renderbuffer()
338 {
339 delete mInstance;
340 }
341
342 // The RenderbufferInterface contained in this Renderbuffer may need to maintain
343 // its own reference count, so we pass it on here.
addRef()344 void Renderbuffer::addRef()
345 {
346 mInstance->addProxyRef(this);
347
348 Object::addRef();
349 }
350
release()351 void Renderbuffer::release()
352 {
353 mInstance->releaseProxy(this);
354
355 Object::release();
356 }
357
358 // Increments refcount on image.
359 // caller must Release() the returned image
getRenderTarget()360 egl::Image *Renderbuffer::getRenderTarget()
361 {
362 return mInstance->getRenderTarget();
363 }
364
365 // Increments refcount on image.
366 // caller must Release() the returned image
createSharedImage()367 egl::Image *Renderbuffer::createSharedImage()
368 {
369 return mInstance->createSharedImage();
370 }
371
isShared() const372 bool Renderbuffer::isShared() const
373 {
374 return mInstance->isShared();
375 }
376
getWidth() const377 GLsizei Renderbuffer::getWidth() const
378 {
379 return mInstance->getWidth();
380 }
381
getHeight() const382 GLsizei Renderbuffer::getHeight() const
383 {
384 return mInstance->getHeight();
385 }
386
getDepth() const387 GLsizei Renderbuffer::getDepth() const
388 {
389 return mInstance->getDepth();
390 }
391
getLevel() const392 GLint Renderbuffer::getLevel() const
393 {
394 return mInstance->getLevel();
395 }
396
getFormat() const397 GLint Renderbuffer::getFormat() const
398 {
399 return mInstance->getFormat();
400 }
401
getRedSize() const402 GLuint Renderbuffer::getRedSize() const
403 {
404 return mInstance->getRedSize();
405 }
406
getGreenSize() const407 GLuint Renderbuffer::getGreenSize() const
408 {
409 return mInstance->getGreenSize();
410 }
411
getBlueSize() const412 GLuint Renderbuffer::getBlueSize() const
413 {
414 return mInstance->getBlueSize();
415 }
416
getAlphaSize() const417 GLuint Renderbuffer::getAlphaSize() const
418 {
419 return mInstance->getAlphaSize();
420 }
421
getDepthSize() const422 GLuint Renderbuffer::getDepthSize() const
423 {
424 return mInstance->getDepthSize();
425 }
426
getStencilSize() const427 GLuint Renderbuffer::getStencilSize() const
428 {
429 return mInstance->getStencilSize();
430 }
431
getSamples() const432 GLsizei Renderbuffer::getSamples() const
433 {
434 return mInstance->getSamples();
435 }
436
setLevel(GLint level)437 void Renderbuffer::setLevel(GLint level)
438 {
439 return mInstance->setLevel(level);
440 }
441
setStorage(RenderbufferStorage * newStorage)442 void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
443 {
444 ASSERT(newStorage);
445
446 delete mInstance;
447 mInstance = newStorage;
448 }
449
RenderbufferStorage()450 RenderbufferStorage::RenderbufferStorage()
451 {
452 mWidth = 0;
453 mHeight = 0;
454 format = GL_NONE;
455 mSamples = 0;
456 }
457
~RenderbufferStorage()458 RenderbufferStorage::~RenderbufferStorage()
459 {
460 }
461
getWidth() const462 GLsizei RenderbufferStorage::getWidth() const
463 {
464 return mWidth;
465 }
466
getHeight() const467 GLsizei RenderbufferStorage::getHeight() const
468 {
469 return mHeight;
470 }
471
getFormat() const472 GLint RenderbufferStorage::getFormat() const
473 {
474 return format;
475 }
476
getSamples() const477 GLsizei RenderbufferStorage::getSamples() const
478 {
479 return mSamples;
480 }
481
Colorbuffer(egl::Image * renderTarget)482 Colorbuffer::Colorbuffer(egl::Image *renderTarget) : mRenderTarget(renderTarget)
483 {
484 if(renderTarget)
485 {
486 renderTarget->addRef();
487
488 mWidth = renderTarget->getWidth();
489 mHeight = renderTarget->getHeight();
490 format = renderTarget->getFormat();
491 mSamples = renderTarget->getDepth() & ~1;
492 }
493 }
494
Colorbuffer(int width,int height,GLenum internalformat,GLsizei samples)495 Colorbuffer::Colorbuffer(int width, int height, GLenum internalformat, GLsizei samples) : mRenderTarget(nullptr)
496 {
497 int supportedSamples = Context::getSupportedMultisampleCount(samples);
498
499 if(width > 0 && height > 0)
500 {
501 if(height > sw::OUTLINE_RESOLUTION)
502 {
503 error(GL_OUT_OF_MEMORY);
504 return;
505 }
506
507 mRenderTarget = egl::Image::create(width, height, internalformat, supportedSamples, false);
508
509 if(!mRenderTarget)
510 {
511 error(GL_OUT_OF_MEMORY);
512 return;
513 }
514 }
515
516 mWidth = width;
517 mHeight = height;
518 format = internalformat;
519 mSamples = supportedSamples;
520 }
521
~Colorbuffer()522 Colorbuffer::~Colorbuffer()
523 {
524 if(mRenderTarget)
525 {
526 mRenderTarget->release();
527 }
528 }
529
530 // Increments refcount on image.
531 // caller must release() the returned image
getRenderTarget()532 egl::Image *Colorbuffer::getRenderTarget()
533 {
534 if(mRenderTarget)
535 {
536 mRenderTarget->addRef();
537 }
538
539 return mRenderTarget;
540 }
541
542 // Increments refcount on image.
543 // caller must release() the returned image
createSharedImage()544 egl::Image *Colorbuffer::createSharedImage()
545 {
546 if(mRenderTarget)
547 {
548 mRenderTarget->addRef();
549 mRenderTarget->markShared();
550 }
551
552 return mRenderTarget;
553 }
554
isShared() const555 bool Colorbuffer::isShared() const
556 {
557 return mRenderTarget->isShared();
558 }
559
DepthStencilbuffer(egl::Image * depthStencil)560 DepthStencilbuffer::DepthStencilbuffer(egl::Image *depthStencil) : mDepthStencil(depthStencil)
561 {
562 if(depthStencil)
563 {
564 depthStencil->addRef();
565
566 mWidth = depthStencil->getWidth();
567 mHeight = depthStencil->getHeight();
568 format = depthStencil->getFormat();
569 mSamples = depthStencil->getDepth() & ~1;
570 }
571 }
572
DepthStencilbuffer(int width,int height,GLenum internalformat,GLsizei samples)573 DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLenum internalformat, GLsizei samples) : mDepthStencil(nullptr)
574 {
575 int supportedSamples = Context::getSupportedMultisampleCount(samples);
576
577 if(width > 0 && height > 0)
578 {
579 if(height > sw::OUTLINE_RESOLUTION)
580 {
581 error(GL_OUT_OF_MEMORY);
582 return;
583 }
584
585 mDepthStencil = egl::Image::create(width, height, internalformat, supportedSamples, false);
586
587 if(!mDepthStencil)
588 {
589 error(GL_OUT_OF_MEMORY);
590 return;
591 }
592 }
593
594 mWidth = width;
595 mHeight = height;
596 format = internalformat;
597 mSamples = supportedSamples;
598 }
599
~DepthStencilbuffer()600 DepthStencilbuffer::~DepthStencilbuffer()
601 {
602 if(mDepthStencil)
603 {
604 mDepthStencil->release();
605 }
606 }
607
608 // Increments refcount on image.
609 // caller must release() the returned image
getRenderTarget()610 egl::Image *DepthStencilbuffer::getRenderTarget()
611 {
612 if(mDepthStencil)
613 {
614 mDepthStencil->addRef();
615 }
616
617 return mDepthStencil;
618 }
619
620 // Increments refcount on image.
621 // caller must release() the returned image
createSharedImage()622 egl::Image *DepthStencilbuffer::createSharedImage()
623 {
624 if(mDepthStencil)
625 {
626 mDepthStencil->addRef();
627 mDepthStencil->markShared();
628 }
629
630 return mDepthStencil;
631 }
632
isShared() const633 bool DepthStencilbuffer::isShared() const
634 {
635 return mDepthStencil->isShared();
636 }
637
Depthbuffer(egl::Image * depthStencil)638 Depthbuffer::Depthbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil)
639 {
640 }
641
Depthbuffer(int width,int height,GLenum internalformat,GLsizei samples)642 Depthbuffer::Depthbuffer(int width, int height, GLenum internalformat, GLsizei samples) : DepthStencilbuffer(width, height, internalformat, samples)
643 {
644 }
645
~Depthbuffer()646 Depthbuffer::~Depthbuffer()
647 {
648 }
649
Stencilbuffer(egl::Image * depthStencil)650 Stencilbuffer::Stencilbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil)
651 {
652 }
653
Stencilbuffer(int width,int height,GLsizei samples)654 Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, GL_STENCIL_INDEX8, samples)
655 {
656 }
657
~Stencilbuffer()658 Stencilbuffer::~Stencilbuffer()
659 {
660 }
661
662 }
663