blob: a16d6879208853dded525a2b6d92577158361396 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Renderbuffer.cpp: the gl::Renderbuffer class and its derived classes
8// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
9// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
10
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011#include "libGLESv2/Renderbuffer.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000012
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000013#include "libGLESv2/main.h"
14#include "libGLESv2/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000015
16namespace gl
17{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000018unsigned int RenderbufferStorage::mCurrentSerial = 1;
daniel@transgaming.com092bd482010-05-12 03:39:36 +000019
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000020Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *storage) : RefCountObject(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000021{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000022 ASSERT(storage != NULL);
23 mStorage = storage;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024}
25
26Renderbuffer::~Renderbuffer()
27{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000028 delete mStorage;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029}
30
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000031bool Renderbuffer::isColorbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000033 return mStorage->isColorbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034}
35
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000036bool Renderbuffer::isDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000037{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000038 return mStorage->isDepthbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000039}
40
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000041bool Renderbuffer::isStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000043 return mStorage->isStencilbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000044}
45
46IDirect3DSurface9 *Renderbuffer::getRenderTarget()
47{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000048 return mStorage->getRenderTarget();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000049}
50
51IDirect3DSurface9 *Renderbuffer::getDepthStencil()
52{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000053 return mStorage->getDepthStencil();
54}
55
56int Renderbuffer::getWidth() const
57{
58 return mStorage->getWidth();
59}
60
61int Renderbuffer::getHeight() const
62{
63 return mStorage->getHeight();
64}
65
66GLenum Renderbuffer::getFormat() const
67{
68 return mStorage->getFormat();
69}
70
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +000071D3DFORMAT Renderbuffer::getD3DFormat() const
72{
73 return mStorage->getD3DFormat();
74}
75
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000076unsigned int Renderbuffer::getSerial() const
77{
78 return mStorage->getSerial();
79}
80
81void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
82{
83 ASSERT(newStorage != NULL);
84
85 delete mStorage;
86 mStorage = newStorage;
87}
88
89RenderbufferStorage::RenderbufferStorage()
90{
91 mSerial = issueSerial();
92}
93
94RenderbufferStorage::~RenderbufferStorage()
95{
96}
97
98bool RenderbufferStorage::isColorbuffer() const
99{
100 return false;
101}
102
103bool RenderbufferStorage::isDepthbuffer() const
104{
105 return false;
106}
107
108bool RenderbufferStorage::isStencilbuffer() const
109{
110 return false;
111}
112
113IDirect3DSurface9 *RenderbufferStorage::getRenderTarget()
114{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115 return NULL;
116}
117
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000118IDirect3DSurface9 *RenderbufferStorage::getDepthStencil()
119{
120 return NULL;
121}
122
123int RenderbufferStorage::getWidth() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124{
125 return mWidth;
126}
127
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000128int RenderbufferStorage::getHeight() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129{
130 return mHeight;
131}
132
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000133void RenderbufferStorage::setSize(int width, int height)
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000134{
135 mWidth = width;
136 mHeight = height;
137}
138
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000139GLenum RenderbufferStorage::getFormat() const
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000140{
141 return mFormat;
142}
143
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000144bool RenderbufferStorage::isFloatingPoint() const
145{
146 return false; // no floating point renderbuffers
147}
148
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000149D3DFORMAT RenderbufferStorage::getD3DFormat() const
150{
151 return mD3DFormat;
152}
153
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000154GLsizei RenderbufferStorage::getSamples() const
155{
156 return mSamples;
157}
158
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000159unsigned int RenderbufferStorage::getSerial() const
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000160{
161 return mSerial;
162}
163
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000164unsigned int RenderbufferStorage::issueSerial()
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000165{
166 return mCurrentSerial++;
167}
168
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
170{
171 if (renderTarget)
172 {
173 renderTarget->AddRef();
174
175 D3DSURFACE_DESC description;
176 renderTarget->GetDesc(&description);
177
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000178 setSize(description.Width, description.Height);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000179 mD3DFormat = description.Format;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000180 mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000181 }
182 else
183 {
184 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000185 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186 }
187}
188
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000189Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000190{
191 IDirect3DDevice9 *device = getDevice();
192
193 mRenderTarget = NULL;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000194 D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000195 int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
196
197 if (supportedSamples == -1)
198 {
199 error(GL_OUT_OF_MEMORY);
200
201 return;
202 }
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000203
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000204 if (width > 0 && height > 0)
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000205 {
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000206 HRESULT result = device->CreateRenderTarget(width, height, requestedFormat,
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000207 es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL);
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000208
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000209 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
210 {
211 error(GL_OUT_OF_MEMORY);
212
213 return;
214 }
215
216 ASSERT(SUCCEEDED(result));
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000217 }
218
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000219 if (mRenderTarget)
220 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000221 setSize(width, height);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000222 mFormat = format;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000223 mD3DFormat = requestedFormat;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000224 mSamples = supportedSamples;
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000225 }
226 else
227 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000228 setSize(0, 0);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000229 mFormat = GL_RGBA4;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000230 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000231 mSamples = 0;
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000232 }
233}
234
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235Colorbuffer::~Colorbuffer()
236{
237 if (mRenderTarget)
238 {
239 mRenderTarget->Release();
240 }
241}
242
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000243bool Colorbuffer::isColorbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244{
245 return true;
246}
247
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000248GLuint Colorbuffer::getRedSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249{
250 if (mRenderTarget)
251 {
252 D3DSURFACE_DESC description;
253 mRenderTarget->GetDesc(&description);
254
255 return es2dx::GetRedSize(description.Format);
256 }
257
258 return 0;
259}
260
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000261GLuint Colorbuffer::getGreenSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262{
263 if (mRenderTarget)
264 {
265 D3DSURFACE_DESC description;
266 mRenderTarget->GetDesc(&description);
267
268 return es2dx::GetGreenSize(description.Format);
269 }
270
271 return 0;
272}
273
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000274GLuint Colorbuffer::getBlueSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275{
276 if (mRenderTarget)
277 {
278 D3DSURFACE_DESC description;
279 mRenderTarget->GetDesc(&description);
280
281 return es2dx::GetBlueSize(description.Format);
282 }
283
284 return 0;
285}
286
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000287GLuint Colorbuffer::getAlphaSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288{
289 if (mRenderTarget)
290 {
291 D3DSURFACE_DESC description;
292 mRenderTarget->GetDesc(&description);
293
294 return es2dx::GetAlphaSize(description.Format);
295 }
296
297 return 0;
298}
299
300IDirect3DSurface9 *Colorbuffer::getRenderTarget()
301{
302 return mRenderTarget;
303}
304
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000305DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306{
307 if (depthStencil)
308 {
309 depthStencil->AddRef();
310
311 D3DSURFACE_DESC description;
312 depthStencil->GetDesc(&description);
313
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000314 setSize(description.Width, description.Height);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000315 mFormat = (description.Format == D3DFMT_D16 ? GL_DEPTH_COMPONENT16 : GL_DEPTH24_STENCIL8_OES);
316 mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000317 mD3DFormat = description.Format;
318 }
319 else
320 {
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000321 mD3DFormat = D3DFMT_UNKNOWN;
322 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323 }
324}
325
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000326DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327{
328 IDirect3DDevice9 *device = getDevice();
329
330 mDepthStencil = NULL;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000331
332 int supportedSamples = getContext()->getNearestSupportedSamples(D3DFMT_D24S8, samples);
333
334 if (supportedSamples == -1)
335 {
336 error(GL_OUT_OF_MEMORY);
337
338 return;
339 }
340
341 HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
342 0, FALSE, &mDepthStencil, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
344 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
345 {
346 error(GL_OUT_OF_MEMORY);
347
348 return;
349 }
350
351 ASSERT(SUCCEEDED(result));
352
353 if (mDepthStencil)
354 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000355 setSize(width, height);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000356 mFormat = GL_DEPTH24_STENCIL8_OES;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000357 mD3DFormat = D3DFMT_D24S8;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000358 mSamples = supportedSamples;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000359 }
360 else
361 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000362 setSize(0, 0);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000363 mFormat = GL_RGBA4; //default format
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000364 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000365 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366 }
367}
368
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000369DepthStencilbuffer::~DepthStencilbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000370{
371 if (mDepthStencil)
372 {
373 mDepthStencil->Release();
374 }
375}
376
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000377bool DepthStencilbuffer::isDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378{
379 return true;
380}
381
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000382bool DepthStencilbuffer::isStencilbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000383{
384 return true;
385}
386
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000387GLuint DepthStencilbuffer::getDepthSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388{
389 if (mDepthStencil)
390 {
391 D3DSURFACE_DESC description;
392 mDepthStencil->GetDesc(&description);
393
daniel@transgaming.com7a2c2802010-03-16 06:23:33 +0000394 return es2dx::GetDepthSize(description.Format);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395 }
396
397 return 0;
398}
399
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000400GLuint DepthStencilbuffer::getStencilSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401{
402 if (mDepthStencil)
403 {
404 D3DSURFACE_DESC description;
405 mDepthStencil->GetDesc(&description);
406
407 return es2dx::GetStencilSize(description.Format);
408 }
409
410 return 0;
411}
412
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000413IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
414{
415 return mDepthStencil;
416}
417
418Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
419{
420 if (depthStencil)
421 {
422 mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
423 // will expect one of the valid renderbuffer formats for use in
424 // glRenderbufferStorage
425 }
426}
427
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000428Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000429{
430 if (getDepthStencil())
431 {
432 mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
433 // will expect one of the valid renderbuffer formats for use in
434 // glRenderbufferStorage
435 }
436}
437
438Depthbuffer::~Depthbuffer()
439{
440}
441
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000442bool Depthbuffer::isDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000443{
444 return true;
445}
446
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000447bool Depthbuffer::isStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000449 return false;
450}
451
452Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
453{
454 if (depthStencil)
455 {
456 mFormat = GL_STENCIL_INDEX8; // 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 else
461 {
462 mFormat = GL_RGBA4; //default format
463 }
464}
465
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000466Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000467{
468 if (getDepthStencil())
469 {
470 mFormat = GL_STENCIL_INDEX8; // 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()
477{
478}
479
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000480bool Stencilbuffer::isDepthbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000481{
482 return false;
483}
484
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000485bool Stencilbuffer::isStencilbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000486{
487 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000488}
489}