1 //
2 // Copyright 2002 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: Implements the renderer-agnostic gl::Renderbuffer class,
8 // GL renderbuffer objects and related functionality.
9 // [OpenGL ES 2.0.24] section 4.4.3 page 108.
10
11 #include "libANGLE/Renderbuffer.h"
12
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/FramebufferAttachment.h"
16 #include "libANGLE/Image.h"
17 #include "libANGLE/Renderbuffer.h"
18 #include "libANGLE/Texture.h"
19 #include "libANGLE/formatutils.h"
20 #include "libANGLE/renderer/GLImplFactory.h"
21 #include "libANGLE/renderer/d3d/RenderTargetD3D.h"
22
23 namespace gl
24 {
25 namespace
26 {
27 angle::SubjectIndex kRenderbufferImplSubjectIndex = 0;
28
DetermineInitState(const Context * context)29 InitState DetermineInitState(const Context *context)
30 {
31 return (context && context->isRobustResourceInitEnabled()) ? InitState::MayNeedInit
32 : InitState::Initialized;
33 }
34 } // namespace
35
36 // RenderbufferState implementation.
RenderbufferState()37 RenderbufferState::RenderbufferState()
38 : mWidth(0),
39 mHeight(0),
40 mFormat(GL_RGBA4),
41 mSamples(0),
42 mMultisamplingMode(MultisamplingMode::Regular),
43 mHasProtectedContent(false),
44 mInitState(InitState::Initialized)
45 {}
46
~RenderbufferState()47 RenderbufferState::~RenderbufferState() {}
48
getWidth() const49 GLsizei RenderbufferState::getWidth() const
50 {
51 return mWidth;
52 }
53
getHeight() const54 GLsizei RenderbufferState::getHeight() const
55 {
56 return mHeight;
57 }
58
getFormat() const59 const Format &RenderbufferState::getFormat() const
60 {
61 return mFormat;
62 }
63
getSamples() const64 GLsizei RenderbufferState::getSamples() const
65 {
66 return mSamples;
67 }
68
getMultisamplingMode() const69 MultisamplingMode RenderbufferState::getMultisamplingMode() const
70 {
71 return mMultisamplingMode;
72 }
73
getInitState() const74 InitState RenderbufferState::getInitState() const
75 {
76 return mInitState;
77 }
78
update(GLsizei width,GLsizei height,const Format & format,GLsizei samples,MultisamplingMode multisamplingMode,InitState initState)79 void RenderbufferState::update(GLsizei width,
80 GLsizei height,
81 const Format &format,
82 GLsizei samples,
83 MultisamplingMode multisamplingMode,
84 InitState initState)
85 {
86 mWidth = width;
87 mHeight = height;
88 mFormat = format;
89 mSamples = samples;
90 mMultisamplingMode = multisamplingMode;
91 mInitState = initState;
92 mHasProtectedContent = false;
93 }
94
setProtectedContent(bool hasProtectedContent)95 void RenderbufferState::setProtectedContent(bool hasProtectedContent)
96 {
97 mHasProtectedContent = hasProtectedContent;
98 }
99
100 // Renderbuffer implementation.
Renderbuffer(rx::GLImplFactory * implFactory,RenderbufferID id)101 Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id)
102 : RefCountObject(implFactory->generateSerial(), id),
103 mState(),
104 mImplementation(implFactory->createRenderbuffer(mState)),
105 mLabel(),
106 mImplObserverBinding(this, kRenderbufferImplSubjectIndex)
107 {
108 mImplObserverBinding.bind(mImplementation.get());
109 }
110
onDestroy(const Context * context)111 void Renderbuffer::onDestroy(const Context *context)
112 {
113 egl::RefCountObjectReleaser<egl::Image> releaseImage;
114 (void)orphanImages(context, &releaseImage);
115
116 if (mImplementation)
117 {
118 mImplementation->onDestroy(context);
119 }
120 }
121
~Renderbuffer()122 Renderbuffer::~Renderbuffer() {}
123
setLabel(const Context * context,const std::string & label)124 void Renderbuffer::setLabel(const Context *context, const std::string &label)
125 {
126 mLabel = label;
127 }
128
getLabel() const129 const std::string &Renderbuffer::getLabel() const
130 {
131 return mLabel;
132 }
133
setStorage(const Context * context,GLenum internalformat,GLsizei width,GLsizei height)134 angle::Result Renderbuffer::setStorage(const Context *context,
135 GLenum internalformat,
136 GLsizei width,
137 GLsizei height)
138 {
139
140 egl::RefCountObjectReleaser<egl::Image> releaseImage;
141 ANGLE_TRY(orphanImages(context, &releaseImage));
142
143 ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height));
144
145 mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular,
146 DetermineInitState(context));
147 onStateChange(angle::SubjectMessage::SubjectChanged);
148
149 return angle::Result::Continue;
150 }
151
setStorageMultisample(const Context * context,GLsizei samplesIn,GLenum internalformat,GLsizei width,GLsizei height,MultisamplingMode mode)152 angle::Result Renderbuffer::setStorageMultisample(const Context *context,
153 GLsizei samplesIn,
154 GLenum internalformat,
155 GLsizei width,
156 GLsizei height,
157 MultisamplingMode mode)
158 {
159 egl::RefCountObjectReleaser<egl::Image> releaseImage;
160 ANGLE_TRY(orphanImages(context, &releaseImage));
161
162 // Potentially adjust "samplesIn" to a supported value
163 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
164 GLsizei samples = formatCaps.getNearestSamples(samplesIn);
165
166 ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width,
167 height, mode));
168
169 mState.update(width, height, Format(internalformat), samples, mode,
170 DetermineInitState(context));
171 onStateChange(angle::SubjectMessage::SubjectChanged);
172
173 return angle::Result::Continue;
174 }
175
setStorageEGLImageTarget(const Context * context,egl::Image * image)176 angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
177 {
178 egl::RefCountObjectReleaser<egl::Image> releaseImage;
179 ANGLE_TRY(orphanImages(context, &releaseImage));
180
181 ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image));
182
183 setTargetImage(context, image);
184
185 mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
186 Format(image->getFormat()), 0, MultisamplingMode::Regular,
187 image->sourceInitState());
188 mState.setProtectedContent(image->hasProtectedContent());
189
190 onStateChange(angle::SubjectMessage::SubjectChanged);
191
192 return angle::Result::Continue;
193 }
194
copyRenderbufferSubData(Context * context,const gl::Renderbuffer * srcBuffer,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)195 angle::Result Renderbuffer::copyRenderbufferSubData(Context *context,
196 const gl::Renderbuffer *srcBuffer,
197 GLint srcLevel,
198 GLint srcX,
199 GLint srcY,
200 GLint srcZ,
201 GLint dstLevel,
202 GLint dstX,
203 GLint dstY,
204 GLint dstZ,
205 GLsizei srcWidth,
206 GLsizei srcHeight,
207 GLsizei srcDepth)
208 {
209 ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY,
210 srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
211 srcHeight, srcDepth));
212
213 return angle::Result::Continue;
214 }
215
copyTextureSubData(Context * context,const gl::Texture * srcTexture,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)216 angle::Result Renderbuffer::copyTextureSubData(Context *context,
217 const gl::Texture *srcTexture,
218 GLint srcLevel,
219 GLint srcX,
220 GLint srcY,
221 GLint srcZ,
222 GLint dstLevel,
223 GLint dstX,
224 GLint dstY,
225 GLint dstZ,
226 GLsizei srcWidth,
227 GLsizei srcHeight,
228 GLsizei srcDepth)
229 {
230 ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
231 dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
232 srcDepth));
233
234 return angle::Result::Continue;
235 }
236
getImplementation() const237 rx::RenderbufferImpl *Renderbuffer::getImplementation() const
238 {
239 ASSERT(mImplementation);
240 return mImplementation.get();
241 }
242
getWidth() const243 GLsizei Renderbuffer::getWidth() const
244 {
245 return mState.mWidth;
246 }
247
getHeight() const248 GLsizei Renderbuffer::getHeight() const
249 {
250 return mState.mHeight;
251 }
252
getFormat() const253 const Format &Renderbuffer::getFormat() const
254 {
255 return mState.mFormat;
256 }
257
getSamples() const258 GLsizei Renderbuffer::getSamples() const
259 {
260 return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0;
261 }
262
getMultisamplingMode() const263 MultisamplingMode Renderbuffer::getMultisamplingMode() const
264 {
265 return mState.mMultisamplingMode;
266 }
267
getRedSize() const268 GLuint Renderbuffer::getRedSize() const
269 {
270 return mState.mFormat.info->redBits;
271 }
272
getGreenSize() const273 GLuint Renderbuffer::getGreenSize() const
274 {
275 return mState.mFormat.info->greenBits;
276 }
277
getBlueSize() const278 GLuint Renderbuffer::getBlueSize() const
279 {
280 return mState.mFormat.info->blueBits;
281 }
282
getAlphaSize() const283 GLuint Renderbuffer::getAlphaSize() const
284 {
285 return mState.mFormat.info->alphaBits;
286 }
287
getDepthSize() const288 GLuint Renderbuffer::getDepthSize() const
289 {
290 return mState.mFormat.info->depthBits;
291 }
292
getStencilSize() const293 GLuint Renderbuffer::getStencilSize() const
294 {
295 return mState.mFormat.info->stencilBits;
296 }
297
getState() const298 const RenderbufferState &Renderbuffer::getState() const
299 {
300 return mState;
301 }
302
getMemorySize() const303 GLint Renderbuffer::getMemorySize() const
304 {
305 GLint implSize = mImplementation->getMemorySize();
306 if (implSize > 0)
307 {
308 return implSize;
309 }
310
311 // Assume allocated size is around width * height * samples * pixelBytes
312 angle::CheckedNumeric<GLint> size = 1;
313 size *= mState.mFormat.info->pixelBytes;
314 size *= mState.mWidth;
315 size *= mState.mHeight;
316 size *= std::max(mState.mSamples, 1);
317 return size.ValueOrDefault(std::numeric_limits<GLint>::max());
318 }
319
onAttach(const Context * context,rx::Serial framebufferSerial)320 void Renderbuffer::onAttach(const Context *context, rx::Serial framebufferSerial)
321 {
322 addRef();
323 }
324
onDetach(const Context * context,rx::Serial framebufferSerial)325 void Renderbuffer::onDetach(const Context *context, rx::Serial framebufferSerial)
326 {
327 release(context);
328 }
329
getId() const330 GLuint Renderbuffer::getId() const
331 {
332 return id().value;
333 }
334
getAttachmentSize(const gl::ImageIndex &) const335 Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
336 {
337 return Extents(mState.mWidth, mState.mHeight, 1);
338 }
339
getAttachmentFormat(GLenum,const ImageIndex &) const340 Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
341 const ImageIndex & /*imageIndex*/) const
342 {
343 return getFormat();
344 }
getAttachmentSamples(const ImageIndex &) const345 GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
346 {
347 return getSamples();
348 }
349
isRenderable(const Context * context,GLenum binding,const ImageIndex & imageIndex) const350 bool Renderbuffer::isRenderable(const Context *context,
351 GLenum binding,
352 const ImageIndex &imageIndex) const
353 {
354 if (isEGLImageTarget())
355 {
356 return ImageSibling::isRenderable(context, binding, imageIndex);
357 }
358 return getFormat().info->renderbufferSupport(context->getClientVersion(),
359 context->getExtensions());
360 }
361
initState(const gl::ImageIndex &) const362 InitState Renderbuffer::initState(const gl::ImageIndex & /*imageIndex*/) const
363 {
364 if (isEGLImageTarget())
365 {
366 return sourceEGLImageInitState();
367 }
368
369 return mState.mInitState;
370 }
371
setInitState(const gl::ImageIndex &,InitState initState)372 void Renderbuffer::setInitState(const gl::ImageIndex & /*imageIndex*/, InitState initState)
373 {
374 if (isEGLImageTarget())
375 {
376 setSourceEGLImageInitState(initState);
377 }
378 else
379 {
380 mState.mInitState = initState;
381 }
382 }
383
getAttachmentImpl() const384 rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
385 {
386 return mImplementation.get();
387 }
388
getImplementationColorReadFormat(const Context * context) const389 GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
390 {
391 return mImplementation->getColorReadFormat(context);
392 }
393
getImplementationColorReadType(const Context * context) const394 GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
395 {
396 return mImplementation->getColorReadType(context);
397 }
398
getRenderbufferImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,GLenum format,GLenum type,void * pixels) const399 angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
400 const PixelPackState &packState,
401 Buffer *packBuffer,
402 GLenum format,
403 GLenum type,
404 void *pixels) const
405 {
406 return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
407 pixels);
408 }
409
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)410 void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
411 {
412 ASSERT(message == angle::SubjectMessage::SubjectChanged);
413 onStateChange(angle::SubjectMessage::ContentsChanged);
414 }
415 } // namespace gl
416