• 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 angle::Result Renderbuffer::setLabel(const Context *context, const std::string &label)
125 {
126     mLabel = label;
127 
128     if (mImplementation)
129     {
130         return mImplementation->onLabelUpdate(context);
131     }
132     return angle::Result::Continue;
133 }
134 
getLabel() const135 const std::string &Renderbuffer::getLabel() const
136 {
137     return mLabel;
138 }
139 
setStorage(const Context * context,GLenum internalformat,GLsizei width,GLsizei height)140 angle::Result Renderbuffer::setStorage(const Context *context,
141                                        GLenum internalformat,
142                                        GLsizei width,
143                                        GLsizei height)
144 {
145 
146     egl::RefCountObjectReleaser<egl::Image> releaseImage;
147     ANGLE_TRY(orphanImages(context, &releaseImage));
148 
149     ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height));
150 
151     mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular,
152                   DetermineInitState(context));
153     onStateChange(angle::SubjectMessage::SubjectChanged);
154 
155     return angle::Result::Continue;
156 }
157 
setStorageMultisample(const Context * context,GLsizei samplesIn,GLenum internalformat,GLsizei width,GLsizei height,MultisamplingMode mode)158 angle::Result Renderbuffer::setStorageMultisample(const Context *context,
159                                                   GLsizei samplesIn,
160                                                   GLenum internalformat,
161                                                   GLsizei width,
162                                                   GLsizei height,
163                                                   MultisamplingMode mode)
164 {
165     egl::RefCountObjectReleaser<egl::Image> releaseImage;
166     ANGLE_TRY(orphanImages(context, &releaseImage));
167 
168     // Potentially adjust "samplesIn" to a supported value
169     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
170     GLsizei samples               = formatCaps.getNearestSamples(samplesIn);
171 
172     ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width,
173                                                      height, mode));
174 
175     mState.update(width, height, Format(internalformat), samples, mode,
176                   DetermineInitState(context));
177     onStateChange(angle::SubjectMessage::SubjectChanged);
178 
179     return angle::Result::Continue;
180 }
181 
setStorageEGLImageTarget(const Context * context,egl::Image * image)182 angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
183 {
184     egl::RefCountObjectReleaser<egl::Image> releaseImage;
185     ANGLE_TRY(orphanImages(context, &releaseImage));
186 
187     ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image));
188 
189     setTargetImage(context, image);
190 
191     mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
192                   Format(image->getFormat()), 0, MultisamplingMode::Regular,
193                   image->sourceInitState());
194     mState.setProtectedContent(image->hasProtectedContent());
195 
196     onStateChange(angle::SubjectMessage::SubjectChanged);
197 
198     return angle::Result::Continue;
199 }
200 
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)201 angle::Result Renderbuffer::copyRenderbufferSubData(Context *context,
202                                                     const gl::Renderbuffer *srcBuffer,
203                                                     GLint srcLevel,
204                                                     GLint srcX,
205                                                     GLint srcY,
206                                                     GLint srcZ,
207                                                     GLint dstLevel,
208                                                     GLint dstX,
209                                                     GLint dstY,
210                                                     GLint dstZ,
211                                                     GLsizei srcWidth,
212                                                     GLsizei srcHeight,
213                                                     GLsizei srcDepth)
214 {
215     ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY,
216                                                        srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
217                                                        srcHeight, srcDepth));
218 
219     return angle::Result::Continue;
220 }
221 
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)222 angle::Result Renderbuffer::copyTextureSubData(Context *context,
223                                                const gl::Texture *srcTexture,
224                                                GLint srcLevel,
225                                                GLint srcX,
226                                                GLint srcY,
227                                                GLint srcZ,
228                                                GLint dstLevel,
229                                                GLint dstX,
230                                                GLint dstY,
231                                                GLint dstZ,
232                                                GLsizei srcWidth,
233                                                GLsizei srcHeight,
234                                                GLsizei srcDepth)
235 {
236     ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
237                                                   dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
238                                                   srcDepth));
239 
240     return angle::Result::Continue;
241 }
242 
getImplementation() const243 rx::RenderbufferImpl *Renderbuffer::getImplementation() const
244 {
245     ASSERT(mImplementation);
246     return mImplementation.get();
247 }
248 
getWidth() const249 GLsizei Renderbuffer::getWidth() const
250 {
251     return mState.mWidth;
252 }
253 
getHeight() const254 GLsizei Renderbuffer::getHeight() const
255 {
256     return mState.mHeight;
257 }
258 
getFormat() const259 const Format &Renderbuffer::getFormat() const
260 {
261     return mState.mFormat;
262 }
263 
getSamples() const264 GLsizei Renderbuffer::getSamples() const
265 {
266     return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0;
267 }
268 
getMultisamplingMode() const269 MultisamplingMode Renderbuffer::getMultisamplingMode() const
270 {
271     return mState.mMultisamplingMode;
272 }
273 
getRedSize() const274 GLuint Renderbuffer::getRedSize() const
275 {
276     return mState.mFormat.info->redBits;
277 }
278 
getGreenSize() const279 GLuint Renderbuffer::getGreenSize() const
280 {
281     return mState.mFormat.info->greenBits;
282 }
283 
getBlueSize() const284 GLuint Renderbuffer::getBlueSize() const
285 {
286     return mState.mFormat.info->blueBits;
287 }
288 
getAlphaSize() const289 GLuint Renderbuffer::getAlphaSize() const
290 {
291     return mState.mFormat.info->alphaBits;
292 }
293 
getDepthSize() const294 GLuint Renderbuffer::getDepthSize() const
295 {
296     return mState.mFormat.info->depthBits;
297 }
298 
getStencilSize() const299 GLuint Renderbuffer::getStencilSize() const
300 {
301     return mState.mFormat.info->stencilBits;
302 }
303 
getState() const304 const RenderbufferState &Renderbuffer::getState() const
305 {
306     return mState;
307 }
308 
getMemorySize() const309 GLint Renderbuffer::getMemorySize() const
310 {
311     GLint implSize = mImplementation->getMemorySize();
312     if (implSize > 0)
313     {
314         return implSize;
315     }
316 
317     // Assume allocated size is around width * height * samples * pixelBytes
318     angle::CheckedNumeric<GLint> size = 1;
319     size *= mState.mFormat.info->pixelBytes;
320     size *= mState.mWidth;
321     size *= mState.mHeight;
322     size *= std::max(mState.mSamples, 1);
323     return size.ValueOrDefault(std::numeric_limits<GLint>::max());
324 }
325 
onAttach(const Context * context,rx::UniqueSerial framebufferSerial)326 void Renderbuffer::onAttach(const Context *context, rx::UniqueSerial framebufferSerial)
327 {
328     addRef();
329 }
330 
onDetach(const Context * context,rx::UniqueSerial framebufferSerial)331 void Renderbuffer::onDetach(const Context *context, rx::UniqueSerial framebufferSerial)
332 {
333     release(context);
334 }
335 
getId() const336 GLuint Renderbuffer::getId() const
337 {
338     return id().value;
339 }
340 
getAttachmentSize(const gl::ImageIndex &) const341 Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
342 {
343     return Extents(mState.mWidth, mState.mHeight, 1);
344 }
345 
getAttachmentFormat(GLenum,const ImageIndex &) const346 Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
347                                          const ImageIndex & /*imageIndex*/) const
348 {
349     return getFormat();
350 }
getAttachmentSamples(const ImageIndex &) const351 GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
352 {
353     return getSamples();
354 }
355 
isRenderable(const Context * context,GLenum binding,const ImageIndex & imageIndex) const356 bool Renderbuffer::isRenderable(const Context *context,
357                                 GLenum binding,
358                                 const ImageIndex &imageIndex) const
359 {
360     if (isEGLImageTarget())
361     {
362         return ImageSibling::isRenderable(context, binding, imageIndex);
363     }
364     return getFormat().info->renderbufferSupport(context->getClientVersion(),
365                                                  context->getExtensions());
366 }
367 
initState(GLenum,const gl::ImageIndex &) const368 InitState Renderbuffer::initState(GLenum /*binding*/, const gl::ImageIndex & /*imageIndex*/) const
369 {
370     if (isEGLImageTarget())
371     {
372         return sourceEGLImageInitState();
373     }
374 
375     return mState.mInitState;
376 }
377 
setInitState(GLenum,const gl::ImageIndex &,InitState initState)378 void Renderbuffer::setInitState(GLenum /*binding*/,
379                                 const gl::ImageIndex & /*imageIndex*/,
380                                 InitState initState)
381 {
382     if (isEGLImageTarget())
383     {
384         setSourceEGLImageInitState(initState);
385     }
386     else
387     {
388         mState.mInitState = initState;
389     }
390 }
391 
getAttachmentImpl() const392 rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
393 {
394     return mImplementation.get();
395 }
396 
getImplementationColorReadFormat(const Context * context) const397 GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
398 {
399     return mImplementation->getColorReadFormat(context);
400 }
401 
getImplementationColorReadType(const Context * context) const402 GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
403 {
404     return mImplementation->getColorReadType(context);
405 }
406 
getRenderbufferImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,GLenum format,GLenum type,void * pixels) const407 angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
408                                                  const PixelPackState &packState,
409                                                  Buffer *packBuffer,
410                                                  GLenum format,
411                                                  GLenum type,
412                                                  void *pixels) const
413 {
414     return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
415                                                  pixels);
416 }
417 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)418 void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
419 {
420     ASSERT(message == angle::SubjectMessage::SubjectChanged);
421     onStateChange(angle::SubjectMessage::ContentsChanged);
422 }
423 }  // namespace gl
424