blob: de8ea074bc8a308bab33c82fc0caa60404b9ac9a [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"
enne@chromium.org0fa74632010-09-21 16:18:52 +000014#include "libGLESv2/Texture.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015#include "libGLESv2/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000016
17namespace gl
18{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000019unsigned int RenderbufferStorage::mCurrentSerial = 1;
daniel@transgaming.com092bd482010-05-12 03:39:36 +000020
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000021Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *storage) : RefCountObject(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000023 ASSERT(storage != NULL);
24 mStorage = storage;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025}
26
27Renderbuffer::~Renderbuffer()
28{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000029 delete mStorage;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030}
31
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000032bool Renderbuffer::isColorbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000034 return mStorage->isColorbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035}
36
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000037bool Renderbuffer::isDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000039 return mStorage->isDepthbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000040}
41
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000042bool Renderbuffer::isStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000044 return mStorage->isStencilbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000045}
46
47IDirect3DSurface9 *Renderbuffer::getRenderTarget()
48{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000049 return mStorage->getRenderTarget();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000050}
51
52IDirect3DSurface9 *Renderbuffer::getDepthStencil()
53{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000054 return mStorage->getDepthStencil();
55}
56
57int Renderbuffer::getWidth() const
58{
59 return mStorage->getWidth();
60}
61
62int Renderbuffer::getHeight() const
63{
64 return mStorage->getHeight();
65}
66
67GLenum Renderbuffer::getFormat() const
68{
69 return mStorage->getFormat();
70}
71
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +000072D3DFORMAT Renderbuffer::getD3DFormat() const
73{
74 return mStorage->getD3DFormat();
75}
76
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000077unsigned int Renderbuffer::getSerial() const
78{
79 return mStorage->getSerial();
80}
81
82void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
83{
84 ASSERT(newStorage != NULL);
85
86 delete mStorage;
87 mStorage = newStorage;
88}
89
90RenderbufferStorage::RenderbufferStorage()
91{
92 mSerial = issueSerial();
93}
94
95RenderbufferStorage::~RenderbufferStorage()
96{
97}
98
99bool RenderbufferStorage::isColorbuffer() const
100{
101 return false;
102}
103
104bool RenderbufferStorage::isDepthbuffer() const
105{
106 return false;
107}
108
109bool RenderbufferStorage::isStencilbuffer() const
110{
111 return false;
112}
113
114IDirect3DSurface9 *RenderbufferStorage::getRenderTarget()
115{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116 return NULL;
117}
118
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000119IDirect3DSurface9 *RenderbufferStorage::getDepthStencil()
120{
121 return NULL;
122}
123
124int RenderbufferStorage::getWidth() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125{
126 return mWidth;
127}
128
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000129int RenderbufferStorage::getHeight() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130{
131 return mHeight;
132}
133
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000134void RenderbufferStorage::setSize(int width, int height)
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000135{
136 mWidth = width;
137 mHeight = height;
138}
139
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000140GLenum RenderbufferStorage::getFormat() const
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000141{
142 return mFormat;
143}
144
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000145bool RenderbufferStorage::isFloatingPoint() const
146{
147 return false; // no floating point renderbuffers
148}
149
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000150D3DFORMAT RenderbufferStorage::getD3DFormat() const
151{
152 return mD3DFormat;
153}
154
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000155GLsizei RenderbufferStorage::getSamples() const
156{
157 return mSamples;
158}
159
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000160unsigned int RenderbufferStorage::getSerial() const
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000161{
162 return mSerial;
163}
164
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000165unsigned int RenderbufferStorage::issueSerial()
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000166{
167 return mCurrentSerial++;
168}
169
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
171{
172 if (renderTarget)
173 {
174 renderTarget->AddRef();
175
176 D3DSURFACE_DESC description;
177 renderTarget->GetDesc(&description);
178
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000179 setSize(description.Width, description.Height);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000180 mD3DFormat = description.Format;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000181 mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000182 }
183 else
184 {
185 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000186 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187 }
188}
189
enne@chromium.org0fa74632010-09-21 16:18:52 +0000190Colorbuffer::Colorbuffer(const Texture* texture) : mRenderTarget(NULL)
191{
192 setSize(texture->getWidth(), texture->getHeight());
193 mD3DFormat = texture->getD3DFormat();
194 mSamples = 0;
195}
196
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000197Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000198{
199 IDirect3DDevice9 *device = getDevice();
200
201 mRenderTarget = NULL;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000202 D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000203 int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
204
205 if (supportedSamples == -1)
206 {
207 error(GL_OUT_OF_MEMORY);
208
209 return;
210 }
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000211
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000212 if (width > 0 && height > 0)
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000213 {
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000214 HRESULT result = device->CreateRenderTarget(width, height, requestedFormat,
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000215 es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL);
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000216
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000217 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
218 {
219 error(GL_OUT_OF_MEMORY);
220
221 return;
222 }
223
224 ASSERT(SUCCEEDED(result));
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000225 }
226
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000227 if (mRenderTarget)
228 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000229 setSize(width, height);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000230 mFormat = format;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000231 mD3DFormat = requestedFormat;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000232 mSamples = supportedSamples;
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000233 }
234 else
235 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000236 setSize(0, 0);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000237 mFormat = GL_RGBA4;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000238 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000239 mSamples = 0;
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000240 }
241}
242
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243Colorbuffer::~Colorbuffer()
244{
245 if (mRenderTarget)
246 {
247 mRenderTarget->Release();
248 }
249}
250
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000251bool Colorbuffer::isColorbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252{
253 return true;
254}
255
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000256GLuint Colorbuffer::getRedSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257{
258 if (mRenderTarget)
259 {
260 D3DSURFACE_DESC description;
261 mRenderTarget->GetDesc(&description);
262
263 return es2dx::GetRedSize(description.Format);
264 }
265
266 return 0;
267}
268
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000269GLuint Colorbuffer::getGreenSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270{
271 if (mRenderTarget)
272 {
273 D3DSURFACE_DESC description;
274 mRenderTarget->GetDesc(&description);
275
276 return es2dx::GetGreenSize(description.Format);
277 }
278
279 return 0;
280}
281
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000282GLuint Colorbuffer::getBlueSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283{
284 if (mRenderTarget)
285 {
286 D3DSURFACE_DESC description;
287 mRenderTarget->GetDesc(&description);
288
289 return es2dx::GetBlueSize(description.Format);
290 }
291
292 return 0;
293}
294
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000295GLuint Colorbuffer::getAlphaSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296{
297 if (mRenderTarget)
298 {
299 D3DSURFACE_DESC description;
300 mRenderTarget->GetDesc(&description);
301
302 return es2dx::GetAlphaSize(description.Format);
303 }
304
305 return 0;
306}
307
308IDirect3DSurface9 *Colorbuffer::getRenderTarget()
309{
310 return mRenderTarget;
311}
312
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000313DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314{
315 if (depthStencil)
316 {
317 depthStencil->AddRef();
318
319 D3DSURFACE_DESC description;
320 depthStencil->GetDesc(&description);
321
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000322 setSize(description.Width, description.Height);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000323 mFormat = (description.Format == D3DFMT_D16 ? GL_DEPTH_COMPONENT16 : GL_DEPTH24_STENCIL8_OES);
324 mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000325 mD3DFormat = description.Format;
326 }
327 else
328 {
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000329 mD3DFormat = D3DFMT_UNKNOWN;
330 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000331 }
332}
333
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000334DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335{
336 IDirect3DDevice9 *device = getDevice();
337
338 mDepthStencil = NULL;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000339
340 int supportedSamples = getContext()->getNearestSupportedSamples(D3DFMT_D24S8, samples);
341
342 if (supportedSamples == -1)
343 {
344 error(GL_OUT_OF_MEMORY);
345
346 return;
347 }
348
349 HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
350 0, FALSE, &mDepthStencil, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351
352 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
353 {
354 error(GL_OUT_OF_MEMORY);
355
356 return;
357 }
358
359 ASSERT(SUCCEEDED(result));
360
361 if (mDepthStencil)
362 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000363 setSize(width, height);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000364 mFormat = GL_DEPTH24_STENCIL8_OES;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000365 mD3DFormat = D3DFMT_D24S8;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000366 mSamples = supportedSamples;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367 }
368 else
369 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000370 setSize(0, 0);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000371 mFormat = GL_RGBA4; //default format
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000372 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000373 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000374 }
375}
376
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000377DepthStencilbuffer::~DepthStencilbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378{
379 if (mDepthStencil)
380 {
381 mDepthStencil->Release();
382 }
383}
384
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000385bool DepthStencilbuffer::isDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386{
387 return true;
388}
389
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000390bool DepthStencilbuffer::isStencilbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000391{
392 return true;
393}
394
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000395GLuint DepthStencilbuffer::getDepthSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396{
397 if (mDepthStencil)
398 {
399 D3DSURFACE_DESC description;
400 mDepthStencil->GetDesc(&description);
401
daniel@transgaming.com7a2c2802010-03-16 06:23:33 +0000402 return es2dx::GetDepthSize(description.Format);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403 }
404
405 return 0;
406}
407
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000408GLuint DepthStencilbuffer::getStencilSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409{
410 if (mDepthStencil)
411 {
412 D3DSURFACE_DESC description;
413 mDepthStencil->GetDesc(&description);
414
415 return es2dx::GetStencilSize(description.Format);
416 }
417
418 return 0;
419}
420
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000421IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
422{
423 return mDepthStencil;
424}
425
426Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
427{
428 if (depthStencil)
429 {
430 mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
431 // will expect one of the valid renderbuffer formats for use in
432 // glRenderbufferStorage
433 }
434}
435
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000436Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000437{
438 if (getDepthStencil())
439 {
440 mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
441 // will expect one of the valid renderbuffer formats for use in
442 // glRenderbufferStorage
443 }
444}
445
446Depthbuffer::~Depthbuffer()
447{
448}
449
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000450bool Depthbuffer::isDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000451{
452 return true;
453}
454
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000455bool Depthbuffer::isStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000456{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000457 return false;
458}
459
460Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
461{
462 if (depthStencil)
463 {
464 mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
465 // will expect one of the valid renderbuffer formats for use in
466 // glRenderbufferStorage
467 }
468 else
469 {
470 mFormat = GL_RGBA4; //default format
471 }
472}
473
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000474Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000475{
476 if (getDepthStencil())
477 {
478 mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
479 // will expect one of the valid renderbuffer formats for use in
480 // glRenderbufferStorage
481 }
482}
483
484Stencilbuffer::~Stencilbuffer()
485{
486}
487
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000488bool Stencilbuffer::isDepthbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000489{
490 return false;
491}
492
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000493bool Stencilbuffer::isStencilbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000494{
495 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496}
497}