xref: /aosp_15_r20/external/angle/src/libANGLE/Renderbuffer.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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_RGBA4),
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 
initState(GLenum,const gl::ImageIndex &) const367 InitState Renderbuffer::initState(GLenum /*binding*/, const gl::ImageIndex & /*imageIndex*/) const
368 {
369     if (isEGLImageTarget())
370     {
371         return sourceEGLImageInitState();
372     }
373 
374     return mState.mInitState;
375 }
376 
setInitState(GLenum,const gl::ImageIndex &,InitState initState)377 void Renderbuffer::setInitState(GLenum /*binding*/,
378                                 const gl::ImageIndex & /*imageIndex*/,
379                                 InitState initState)
380 {
381     if (isEGLImageTarget())
382     {
383         setSourceEGLImageInitState(initState);
384     }
385     else
386     {
387         mState.mInitState = initState;
388     }
389 }
390 
getAttachmentImpl() const391 rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
392 {
393     return mImplementation.get();
394 }
395 
getImplementationColorReadFormat(const Context * context) const396 GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
397 {
398     return mImplementation->getColorReadFormat(context);
399 }
400 
getImplementationColorReadType(const Context * context) const401 GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
402 {
403     return mImplementation->getColorReadType(context);
404 }
405 
getRenderbufferImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,GLenum format,GLenum type,void * pixels) const406 angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
407                                                  const PixelPackState &packState,
408                                                  Buffer *packBuffer,
409                                                  GLenum format,
410                                                  GLenum type,
411                                                  void *pixels) const
412 {
413     return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
414                                                  pixels);
415 }
416 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)417 void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
418 {
419     ASSERT(message == angle::SubjectMessage::SubjectChanged);
420     onStateChange(angle::SubjectMessage::ContentsChanged);
421 }
422 }  // namespace gl
423