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