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 es1
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 sw2es::GetRedSize(getInternalFormat());
45}
46
47GLuint RenderbufferInterface::getGreenSize() const
48{
49	return sw2es::GetGreenSize(getInternalFormat());
50}
51
52GLuint RenderbufferInterface::getBlueSize() const
53{
54	return sw2es::GetBlueSize(getInternalFormat());
55}
56
57GLuint RenderbufferInterface::getAlphaSize() const
58{
59	return sw2es::GetAlphaSize(getInternalFormat());
60}
61
62GLuint RenderbufferInterface::getDepthSize() const
63{
64	return sw2es::GetDepthSize(getInternalFormat());
65}
66
67GLuint RenderbufferInterface::getStencilSize() const
68{
69	return sw2es::GetStencilSize(getInternalFormat());
70}
71
72///// RenderbufferTexture2D Implementation ////////
73
74RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture)
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, 0);
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, 0);
108}
109
110bool RenderbufferTexture2D::isShared() const
111{
112	return mTexture2D->isShared(GL_TEXTURE_2D, 0);
113}
114
115GLsizei RenderbufferTexture2D::getWidth() const
116{
117	return mTexture2D->getWidth(GL_TEXTURE_2D, 0);
118}
119
120GLsizei RenderbufferTexture2D::getHeight() const
121{
122	return mTexture2D->getHeight(GL_TEXTURE_2D, 0);
123}
124
125GLenum RenderbufferTexture2D::getFormat() const
126{
127	return mTexture2D->getFormat(GL_TEXTURE_2D, 0);
128}
129
130sw::Format RenderbufferTexture2D::getInternalFormat() const
131{
132	return mTexture2D->getInternalFormat(GL_TEXTURE_2D, 0);
133}
134
135GLsizei RenderbufferTexture2D::getSamples() const
136{
137	return 0;
138}
139
140////// Renderbuffer Implementation //////
141
142Renderbuffer::Renderbuffer(GLuint name, RenderbufferInterface *instance) : NamedObject(name)
143{
144	ASSERT(instance);
145	mInstance = instance;
146}
147
148Renderbuffer::~Renderbuffer()
149{
150	delete mInstance;
151}
152
153// The RenderbufferInterface contained in this Renderbuffer may need to maintain
154// its own reference count, so we pass it on here.
155void Renderbuffer::addRef()
156{
157	mInstance->addProxyRef(this);
158
159	Object::addRef();
160}
161
162void Renderbuffer::release()
163{
164	mInstance->releaseProxy(this);
165
166	Object::release();
167}
168
169// Increments refcount on image.
170// caller must Release() the returned image
171egl::Image *Renderbuffer::getRenderTarget()
172{
173	return mInstance->getRenderTarget();
174}
175
176// Increments refcount on image.
177// caller must Release() the returned image
178egl::Image *Renderbuffer::createSharedImage()
179{
180	return mInstance->createSharedImage();
181}
182
183bool Renderbuffer::isShared() const
184{
185	return mInstance->isShared();
186}
187
188GLsizei Renderbuffer::getWidth() const
189{
190	return mInstance->getWidth();
191}
192
193GLsizei Renderbuffer::getHeight() const
194{
195	return mInstance->getHeight();
196}
197
198GLenum Renderbuffer::getFormat() const
199{
200	return mInstance->getFormat();
201}
202
203sw::Format Renderbuffer::getInternalFormat() const
204{
205	return mInstance->getInternalFormat();
206}
207
208GLuint Renderbuffer::getRedSize() const
209{
210	return mInstance->getRedSize();
211}
212
213GLuint Renderbuffer::getGreenSize() const
214{
215	return mInstance->getGreenSize();
216}
217
218GLuint Renderbuffer::getBlueSize() const
219{
220	return mInstance->getBlueSize();
221}
222
223GLuint Renderbuffer::getAlphaSize() const
224{
225	return mInstance->getAlphaSize();
226}
227
228GLuint Renderbuffer::getDepthSize() const
229{
230	return mInstance->getDepthSize();
231}
232
233GLuint Renderbuffer::getStencilSize() const
234{
235	return mInstance->getStencilSize();
236}
237
238GLsizei Renderbuffer::getSamples() const
239{
240	return mInstance->getSamples();
241}
242
243void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
244{
245	ASSERT(newStorage);
246
247	delete mInstance;
248	mInstance = newStorage;
249}
250
251RenderbufferStorage::RenderbufferStorage()
252{
253	mWidth = 0;
254	mHeight = 0;
255	format = GL_RGBA4_OES;
256	internalFormat = sw::FORMAT_A8B8G8R8;
257	mSamples = 0;
258}
259
260RenderbufferStorage::~RenderbufferStorage()
261{
262}
263
264GLsizei RenderbufferStorage::getWidth() const
265{
266	return mWidth;
267}
268
269GLsizei RenderbufferStorage::getHeight() const
270{
271	return mHeight;
272}
273
274GLenum RenderbufferStorage::getFormat() const
275{
276	return format;
277}
278
279sw::Format RenderbufferStorage::getInternalFormat() const
280{
281	return internalFormat;
282}
283
284GLsizei RenderbufferStorage::getSamples() const
285{
286	return mSamples;
287}
288
289Colorbuffer::Colorbuffer(egl::Image *renderTarget) : mRenderTarget(renderTarget)
290{
291	if(renderTarget)
292	{
293		renderTarget->addRef();
294
295		mWidth = renderTarget->getWidth();
296		mHeight = renderTarget->getHeight();
297		internalFormat = renderTarget->getInternalFormat();
298		format = sw2es::ConvertBackBufferFormat(internalFormat);
299		mSamples = renderTarget->getDepth() & ~1;
300	}
301}
302
303Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(nullptr)
304{
305	Device *device = getDevice();
306
307	sw::Format requestedFormat = es2sw::ConvertRenderbufferFormat(format);
308	int supportedSamples = Context::getSupportedMultisampleCount(samples);
309
310	if(width > 0 && height > 0)
311	{
312		mRenderTarget = device->createRenderTarget(width, height, requestedFormat, supportedSamples, false);
313
314		if(!mRenderTarget)
315		{
316			error(GL_OUT_OF_MEMORY);
317			return;
318		}
319	}
320
321	mWidth = width;
322	mHeight = height;
323	this->format = format;
324	internalFormat = requestedFormat;
325	mSamples = supportedSamples;
326}
327
328Colorbuffer::~Colorbuffer()
329{
330	if(mRenderTarget)
331	{
332		mRenderTarget->release();
333	}
334}
335
336// Increments refcount on image.
337// caller must release() the returned image
338egl::Image *Colorbuffer::getRenderTarget()
339{
340	if(mRenderTarget)
341	{
342		mRenderTarget->addRef();
343	}
344
345	return mRenderTarget;
346}
347
348// Increments refcount on image.
349// caller must release() the returned image
350egl::Image *Colorbuffer::createSharedImage()
351{
352	if(mRenderTarget)
353	{
354		mRenderTarget->addRef();
355		mRenderTarget->markShared();
356	}
357
358	return mRenderTarget;
359}
360
361bool Colorbuffer::isShared() const
362{
363	return mRenderTarget->isShared();
364}
365
366DepthStencilbuffer::DepthStencilbuffer(egl::Image *depthStencil) : mDepthStencil(depthStencil)
367{
368	if(depthStencil)
369	{
370		depthStencil->addRef();
371
372		mWidth = depthStencil->getWidth();
373		mHeight = depthStencil->getHeight();
374		internalFormat = depthStencil->getInternalFormat();
375		format = sw2es::ConvertDepthStencilFormat(internalFormat);
376		mSamples = depthStencil->getDepth() & ~1;
377	}
378}
379
380DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) : mDepthStencil(nullptr)
381{
382	Device *device = getDevice();
383
384	int supportedSamples = Context::getSupportedMultisampleCount(samples);
385
386	if(width > 0 && height > 0)
387	{
388		mDepthStencil = device->createDepthStencilSurface(width, height, sw::FORMAT_D24S8, supportedSamples, false);
389
390		if(!mDepthStencil)
391		{
392			error(GL_OUT_OF_MEMORY);
393			return;
394		}
395	}
396
397	mWidth = width;
398	mHeight = height;
399	format = GL_DEPTH24_STENCIL8_OES;
400	internalFormat = sw::FORMAT_D24S8;
401	mSamples = supportedSamples;
402}
403
404DepthStencilbuffer::~DepthStencilbuffer()
405{
406	if(mDepthStencil)
407	{
408		mDepthStencil->release();
409	}
410}
411
412// Increments refcount on image.
413// caller must release() the returned image
414egl::Image *DepthStencilbuffer::getRenderTarget()
415{
416	if(mDepthStencil)
417	{
418		mDepthStencil->addRef();
419	}
420
421	return mDepthStencil;
422}
423
424// Increments refcount on image.
425// caller must release() the returned image
426egl::Image *DepthStencilbuffer::createSharedImage()
427{
428	if(mDepthStencil)
429	{
430		mDepthStencil->addRef();
431		mDepthStencil->markShared();
432	}
433
434	return mDepthStencil;
435}
436
437bool DepthStencilbuffer::isShared() const
438{
439	return mDepthStencil->isShared();
440}
441
442Depthbuffer::Depthbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil)
443{
444	if(depthStencil)
445	{
446		format = GL_DEPTH_COMPONENT16_OES;   // If the renderbuffer parameters are queried, the calling function
447		                                     // will expect one of the valid renderbuffer formats for use in
448		                                     // glRenderbufferStorage
449	}
450}
451
452Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
453{
454	if(mDepthStencil)
455	{
456		format = GL_DEPTH_COMPONENT16_OES;   // If the renderbuffer parameters are queried, the calling function
457		                                     // will expect one of the valid renderbuffer formats for use in
458		                                     // glRenderbufferStorage
459	}
460}
461
462Depthbuffer::~Depthbuffer()
463{
464}
465
466Stencilbuffer::Stencilbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil)
467{
468	if(depthStencil)
469	{
470		format = GL_STENCIL_INDEX8_OES;   // If the renderbuffer parameters are queried, the calling function
471		                                  // will expect one of the valid renderbuffer formats for use in
472		                                  // glRenderbufferStorage
473	}
474}
475
476Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
477{
478	if(mDepthStencil)
479	{
480		format = GL_STENCIL_INDEX8_OES;   // If the renderbuffer parameters are queried, the calling function
481		                                  // will expect one of the valid renderbuffer formats for use in
482		                                  // glRenderbufferStorage
483	}
484}
485
486Stencilbuffer::~Stencilbuffer()
487{
488}
489
490}
491