blob: 0eb4637d3a4dd1d56bd90f74db62a522e2841ec1 [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.com4cbc5902010-08-24 19:20:26 +0000144D3DFORMAT RenderbufferStorage::getD3DFormat() const
145{
146 return mD3DFormat;
147}
148
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000149GLsizei RenderbufferStorage::getSamples() const
150{
151 return mSamples;
152}
153
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000154unsigned int RenderbufferStorage::getSerial() const
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000155{
156 return mSerial;
157}
158
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000159unsigned int RenderbufferStorage::issueSerial()
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000160{
161 return mCurrentSerial++;
162}
163
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
165{
166 if (renderTarget)
167 {
168 renderTarget->AddRef();
169
170 D3DSURFACE_DESC description;
171 renderTarget->GetDesc(&description);
172
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000173 setSize(description.Width, description.Height);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000174 mD3DFormat = description.Format;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000175 mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000176 }
177 else
178 {
179 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000180 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181 }
182}
183
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000184Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000185{
186 IDirect3DDevice9 *device = getDevice();
187
188 mRenderTarget = NULL;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000189 D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000190 int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
191
192 if (supportedSamples == -1)
193 {
194 error(GL_OUT_OF_MEMORY);
195
196 return;
197 }
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000198
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000199 if (width > 0 && height > 0)
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000200 {
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000201 HRESULT result = device->CreateRenderTarget(width, height, requestedFormat,
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000202 es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL);
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000203
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000204 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
205 {
206 error(GL_OUT_OF_MEMORY);
207
208 return;
209 }
210
211 ASSERT(SUCCEEDED(result));
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000212 }
213
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000214 if (mRenderTarget)
215 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000216 setSize(width, height);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000217 mFormat = format;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000218 mD3DFormat = requestedFormat;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000219 mSamples = supportedSamples;
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000220 }
221 else
222 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000223 setSize(0, 0);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000224 mFormat = GL_RGBA4;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000225 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000226 mSamples = 0;
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000227 }
228}
229
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230Colorbuffer::~Colorbuffer()
231{
232 if (mRenderTarget)
233 {
234 mRenderTarget->Release();
235 }
236}
237
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000238bool Colorbuffer::isColorbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239{
240 return true;
241}
242
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000243GLuint Colorbuffer::getRedSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244{
245 if (mRenderTarget)
246 {
247 D3DSURFACE_DESC description;
248 mRenderTarget->GetDesc(&description);
249
250 return es2dx::GetRedSize(description.Format);
251 }
252
253 return 0;
254}
255
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000256GLuint Colorbuffer::getGreenSize() 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::GetGreenSize(description.Format);
264 }
265
266 return 0;
267}
268
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000269GLuint Colorbuffer::getBlueSize() 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::GetBlueSize(description.Format);
277 }
278
279 return 0;
280}
281
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000282GLuint Colorbuffer::getAlphaSize() 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::GetAlphaSize(description.Format);
290 }
291
292 return 0;
293}
294
295IDirect3DSurface9 *Colorbuffer::getRenderTarget()
296{
297 return mRenderTarget;
298}
299
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000300DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301{
302 if (depthStencil)
303 {
304 depthStencil->AddRef();
305
306 D3DSURFACE_DESC description;
307 depthStencil->GetDesc(&description);
308
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000309 setSize(description.Width, description.Height);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000310 mFormat = (description.Format == D3DFMT_D16 ? GL_DEPTH_COMPONENT16 : GL_DEPTH24_STENCIL8_OES);
311 mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000312 mD3DFormat = description.Format;
313 }
314 else
315 {
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000316 mD3DFormat = D3DFMT_UNKNOWN;
317 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318 }
319}
320
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000321DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000322{
323 IDirect3DDevice9 *device = getDevice();
324
325 mDepthStencil = NULL;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000326
327 int supportedSamples = getContext()->getNearestSupportedSamples(D3DFMT_D24S8, samples);
328
329 if (supportedSamples == -1)
330 {
331 error(GL_OUT_OF_MEMORY);
332
333 return;
334 }
335
336 HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
337 0, FALSE, &mDepthStencil, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338
339 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
340 {
341 error(GL_OUT_OF_MEMORY);
342
343 return;
344 }
345
346 ASSERT(SUCCEEDED(result));
347
348 if (mDepthStencil)
349 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000350 setSize(width, height);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000351 mFormat = GL_DEPTH24_STENCIL8_OES;
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000352 mD3DFormat = D3DFMT_D24S8;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000353 mSamples = supportedSamples;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354 }
355 else
356 {
daniel@transgaming.com866f3182010-05-20 19:28:22 +0000357 setSize(0, 0);
daniel@transgaming.com4901fca2010-04-20 18:52:41 +0000358 mFormat = GL_RGBA4; //default format
daniel@transgaming.comca7c0082010-08-24 19:20:20 +0000359 mD3DFormat = D3DFMT_UNKNOWN;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000360 mSamples = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000361 }
362}
363
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000364DepthStencilbuffer::~DepthStencilbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365{
366 if (mDepthStencil)
367 {
368 mDepthStencil->Release();
369 }
370}
371
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000372bool DepthStencilbuffer::isDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000373{
374 return true;
375}
376
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000377bool DepthStencilbuffer::isStencilbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000378{
379 return true;
380}
381
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000382GLuint DepthStencilbuffer::getDepthSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383{
384 if (mDepthStencil)
385 {
386 D3DSURFACE_DESC description;
387 mDepthStencil->GetDesc(&description);
388
daniel@transgaming.com7a2c2802010-03-16 06:23:33 +0000389 return es2dx::GetDepthSize(description.Format);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390 }
391
392 return 0;
393}
394
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000395GLuint DepthStencilbuffer::getStencilSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396{
397 if (mDepthStencil)
398 {
399 D3DSURFACE_DESC description;
400 mDepthStencil->GetDesc(&description);
401
402 return es2dx::GetStencilSize(description.Format);
403 }
404
405 return 0;
406}
407
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000408IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
409{
410 return mDepthStencil;
411}
412
413Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
414{
415 if (depthStencil)
416 {
417 mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
418 // will expect one of the valid renderbuffer formats for use in
419 // glRenderbufferStorage
420 }
421}
422
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000423Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000424{
425 if (getDepthStencil())
426 {
427 mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
428 // will expect one of the valid renderbuffer formats for use in
429 // glRenderbufferStorage
430 }
431}
432
433Depthbuffer::~Depthbuffer()
434{
435}
436
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000437bool Depthbuffer::isDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000438{
439 return true;
440}
441
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000442bool Depthbuffer::isStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000443{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000444 return false;
445}
446
447Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
448{
449 if (depthStencil)
450 {
451 mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
452 // will expect one of the valid renderbuffer formats for use in
453 // glRenderbufferStorage
454 }
455 else
456 {
457 mFormat = GL_RGBA4; //default format
458 }
459}
460
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000461Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000462{
463 if (getDepthStencil())
464 {
465 mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
466 // will expect one of the valid renderbuffer formats for use in
467 // glRenderbufferStorage
468 }
469}
470
471Stencilbuffer::~Stencilbuffer()
472{
473}
474
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000475bool Stencilbuffer::isDepthbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000476{
477 return false;
478}
479
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000480bool Stencilbuffer::isStencilbuffer() const
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000481{
482 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483}
484}