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