• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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