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
25namespace es2
26{
27RenderbufferInterface::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.
34void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy)
35{
36}
37
38void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy)
39{
40}
41
42GLuint RenderbufferInterface::getRedSize() const
43{
44 return GetRedSize(getFormat());
45}
46
47GLuint RenderbufferInterface::getGreenSize() const
48{
49 return GetGreenSize(getFormat());
50}
51
52GLuint RenderbufferInterface::getBlueSize() const
53{
54 return GetBlueSize(getFormat());
55}
56
57GLuint RenderbufferInterface::getAlphaSize() const
58{
59 return GetAlphaSize(getFormat());
60}
61
62GLuint RenderbufferInterface::getDepthSize() const
63{
64 return GetDepthSize(getFormat());
65}
66
67GLuint RenderbufferInterface::getStencilSize() const
68{
69 return GetStencilSize(getFormat());
70}
71
72///// RenderbufferTexture2D Implementation ////////
73
74RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : mLevel(level)
75{
76 mTexture2D = texture;
77}
78
79RenderbufferTexture2D::~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.
86void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy)
87{
88 mTexture2D->addProxyRef(proxy);
89}
90
91void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy)
92{
93 mTexture2D->releaseProxy(proxy);
94}
95
96// Increments refcount on image.
97// caller must release() the returned image
98egl::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
105egl::Image *RenderbufferTexture2D::createSharedImage()
106{
107 return mTexture2D->createSharedImage(GL_TEXTURE_2D, mLevel);
108}
109
110bool RenderbufferTexture2D::isShared() const
111{
112 return mTexture2D->isShared(GL_TEXTURE_2D, mLevel);
113}
114
115GLsizei RenderbufferTexture2D::getWidth() const
116{
117 return mTexture2D->getWidth(GL_TEXTURE_2D, mLevel);
118}
119
120GLsizei RenderbufferTexture2D::getHeight() const
121{
122 return mTexture2D->getHeight(GL_TEXTURE_2D, mLevel);
123}
124
125GLint RenderbufferTexture2D::getFormat() const
126{
127 return mTexture2D->getFormat(GL_TEXTURE_2D, mLevel);
128}
129
130GLsizei RenderbufferTexture2D::getSamples() const
131{
132 return 0; // Core OpenGL ES 3.0 does not support multisample textures.
133}
134
135///// RenderbufferTexture2DRect Implementation ////////
136
137RenderbufferTexture2DRect::RenderbufferTexture2DRect(Texture2DRect *texture)
138{
139 mTexture2DRect = texture;
140}
141
142RenderbufferTexture2DRect::~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.
149void RenderbufferTexture2DRect::addProxyRef(const Renderbuffer *proxy)
150{
151 mTexture2DRect->addProxyRef(proxy);
152}
153
154void RenderbufferTexture2DRect::releaseProxy(const Renderbuffer *proxy)
155{
156 mTexture2DRect->releaseProxy(proxy);
157}
158
159// Increments refcount on image.
160// caller must release() the returned image
161egl::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
168egl::Image *RenderbufferTexture2DRect::createSharedImage()
169{
170 return mTexture2DRect->createSharedImage(GL_TEXTURE_RECTANGLE_ARB, 0);
171}
172
173bool RenderbufferTexture2DRect::isShared() const
174{
175 return mTexture2DRect->isShared(GL_TEXTURE_RECTANGLE_ARB, 0);
176}
177
178GLsizei RenderbufferTexture2DRect::getWidth() const
179{
180 return mTexture2DRect->getWidth(GL_TEXTURE_RECTANGLE_ARB, 0);
181}
182
183GLsizei RenderbufferTexture2DRect::getHeight() const
184{
185 return mTexture2DRect->getHeight(GL_TEXTURE_RECTANGLE_ARB, 0);
186}
187
188GLint RenderbufferTexture2DRect::getFormat() const
189{
190 return mTexture2DRect->getFormat(GL_TEXTURE_RECTANGLE_ARB, 0);
191}
192
193GLsizei RenderbufferTexture2DRect::getSamples() const
194{
195 return 0; // Core OpenGL ES 3.0 does not support multisample textures.
196}
197
198///// RenderbufferTexture3D Implementation ////////
199
200RenderbufferTexture3D::RenderbufferTexture3D(Texture3D *texture, GLint level) : mLevel(level)
201{
202 mTexture3D = texture;
203}
204
205RenderbufferTexture3D::~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.
212void RenderbufferTexture3D::addProxyRef(const Renderbuffer *proxy)
213{
214 mTexture3D->addProxyRef(proxy);
215}
216
217void RenderbufferTexture3D::releaseProxy(const Renderbuffer *proxy)
218{
219 mTexture3D->releaseProxy(proxy);
220}
221
222// Increments refcount on image.
223// caller must release() the returned image
224egl::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
231egl::Image *RenderbufferTexture3D::createSharedImage()
232{
233 return mTexture3D->createSharedImage(mTexture3D->getTarget(), mLevel);
234}
235
236bool RenderbufferTexture3D::isShared() const
237{
238 return mTexture3D->isShared(mTexture3D->getTarget(), mLevel);
239}
240
241GLsizei RenderbufferTexture3D::getWidth() const
242{
243 return mTexture3D->getWidth(mTexture3D->getTarget(), mLevel);
244}
245
246GLsizei RenderbufferTexture3D::getHeight() const
247{
248 return mTexture3D->getHeight(mTexture3D->getTarget(), mLevel);
249}
250
251GLsizei RenderbufferTexture3D::getDepth() const
252{
253 return mTexture3D->getDepth(mTexture3D->getTarget(), mLevel);
254}
255
256GLint RenderbufferTexture3D::getFormat() const
257{
258 return mTexture3D->getFormat(mTexture3D->getTarget(), mLevel);
259}
260
261GLsizei RenderbufferTexture3D::getSamples() const
262{
263 return 0; // Core OpenGL ES 3.0 does not support multisample textures.
264}
265
266///// RenderbufferTextureCubeMap Implementation ////////
267
268RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target, GLint level) : mTarget(target), mLevel(level)
269{
270 mTextureCubeMap = texture;
271}
272
273RenderbufferTextureCubeMap::~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.
280void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy)
281{
282 mTextureCubeMap->addProxyRef(proxy);
283}
284
285void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy)
286{
287 mTextureCubeMap->releaseProxy(proxy);
288}
289
290// Increments refcount on image.
291// caller must release() the returned image
292egl::Image *RenderbufferTextureCubeMap::getRenderTarget()
293{
294 return mTextureCubeMap->getRenderTarget(mTarget, mLevel);
295}
296
297// Increments refcount on image.
298// caller must release() the returned image
299egl::Image *RenderbufferTextureCubeMap::createSharedImage()
300{
301 return mTextureCubeMap->createSharedImage(mTarget, mLevel);
302}
303
304bool RenderbufferTextureCubeMap::isShared() const
305{
306 return mTextureCubeMap->isShared(mTarget, mLevel);
307}
308
309GLsizei RenderbufferTextureCubeMap::getWidth() const
310{
311 return mTextureCubeMap->getWidth(mTarget, mLevel);
312}
313
314GLsizei RenderbufferTextureCubeMap::getHeight() const
315{
316 return mTextureCubeMap->getHeight(mTarget, mLevel);
317}
318
319GLint RenderbufferTextureCubeMap::getFormat() const
320{
321 return mTextureCubeMap->getFormat(mTarget, mLevel);
322}
323
324GLsizei RenderbufferTextureCubeMap::getSamples() const
325{
326 return 0; // Core OpenGL ES 3.0 does not support multisample textures.
327}
328
329////// Renderbuffer Implementation //////
330
331Renderbuffer::Renderbuffer(GLuint name, RenderbufferInterface *instance) : NamedObject(name)
332{
333 ASSERT(instance);
334 mInstance = instance;
335}
336
337Renderbuffer::~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.
344void Renderbuffer::addRef()
345{
346 mInstance->addProxyRef(this);
347
348 Object::addRef();
349}
350
351void 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
360egl::Image *Renderbuffer::getRenderTarget()
361{
362 return mInstance->getRenderTarget();
363}
364
365// Increments refcount on image.
366// caller must Release() the returned image
367egl::Image *Renderbuffer::createSharedImage()
368{
369 return mInstance->createSharedImage();
370}
371
372bool Renderbuffer::isShared() const
373{
374 return mInstance->isShared();
375}
376
377GLsizei Renderbuffer::getWidth() const
378{
379 return mInstance->getWidth();
380}
381
382GLsizei Renderbuffer::getHeight() const
383{
384 return mInstance->getHeight();
385}
386
387GLsizei Renderbuffer::getDepth() const
388{
389 return mInstance->getDepth();
390}
391
392GLint Renderbuffer::getLevel() const
393{
394 return mInstance->getLevel();
395}
396
397GLint Renderbuffer::getFormat() const
398{
399 return mInstance->getFormat();
400}
401
402GLuint Renderbuffer::getRedSize() const
403{
404 return mInstance->getRedSize();
405}
406
407GLuint Renderbuffer::getGreenSize() const
408{
409 return mInstance->getGreenSize();
410}
411
412GLuint Renderbuffer::getBlueSize() const
413{
414 return mInstance->getBlueSize();
415}
416
417GLuint Renderbuffer::getAlphaSize() const
418{
419 return mInstance->getAlphaSize();
420}
421
422GLuint Renderbuffer::getDepthSize() const
423{
424 return mInstance->getDepthSize();
425}
426
427GLuint Renderbuffer::getStencilSize() const
428{
429 return mInstance->getStencilSize();
430}
431
432GLsizei Renderbuffer::getSamples() const
433{
434 return mInstance->getSamples();
435}
436
437void Renderbuffer::setLevel(GLint level)
438{
439 return mInstance->setLevel(level);
440}
441
442void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
443{
444 ASSERT(newStorage);
445
446 delete mInstance;
447 mInstance = newStorage;
448}
449
450RenderbufferStorage::RenderbufferStorage()
451{
452 mWidth = 0;
453 mHeight = 0;
454 format = GL_NONE;
455 mSamples = 0;
456}
457
458RenderbufferStorage::~RenderbufferStorage()
459{
460}
461
462GLsizei RenderbufferStorage::getWidth() const
463{
464 return mWidth;
465}
466
467GLsizei RenderbufferStorage::getHeight() const
468{
469 return mHeight;
470}
471
472GLint RenderbufferStorage::getFormat() const
473{
474 return format;
475}
476
477GLsizei RenderbufferStorage::getSamples() const
478{
479 return mSamples;
480}
481
482Colorbuffer::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
495Colorbuffer::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
522Colorbuffer::~Colorbuffer()
523{
524 if(mRenderTarget)
525 {
526 mRenderTarget->release();
527 }
528}
529
530// Increments refcount on image.
531// caller must release() the returned image
532egl::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
544egl::Image *Colorbuffer::createSharedImage()
545{
546 if(mRenderTarget)
547 {
548 mRenderTarget->addRef();
549 mRenderTarget->markShared();
550 }
551
552 return mRenderTarget;
553}
554
555bool Colorbuffer::isShared() const
556{
557 return mRenderTarget->isShared();
558}
559
560DepthStencilbuffer::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
573DepthStencilbuffer::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
600DepthStencilbuffer::~DepthStencilbuffer()
601{
602 if(mDepthStencil)
603 {
604 mDepthStencil->release();
605 }
606}
607
608// Increments refcount on image.
609// caller must release() the returned image
610egl::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
622egl::Image *DepthStencilbuffer::createSharedImage()
623{
624 if(mDepthStencil)
625 {
626 mDepthStencil->addRef();
627 mDepthStencil->markShared();
628 }
629
630 return mDepthStencil;
631}
632
633bool DepthStencilbuffer::isShared() const
634{
635 return mDepthStencil->isShared();
636}
637
638Depthbuffer::Depthbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil)
639{
640}
641
642Depthbuffer::Depthbuffer(int width, int height, GLenum internalformat, GLsizei samples) : DepthStencilbuffer(width, height, internalformat, samples)
643{
644}
645
646Depthbuffer::~Depthbuffer()
647{
648}
649
650Stencilbuffer::Stencilbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil)
651{
652}
653
654Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, GL_STENCIL_INDEX8, samples)
655{
656}
657
658Stencilbuffer::~Stencilbuffer()
659{
660}
661
662}
663