• 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 }  // namespace
29 
30 // RenderbufferState implementation.
RenderbufferState()31 RenderbufferState::RenderbufferState()
32     : mWidth(0),
33       mHeight(0),
34       mFormat(GL_RGBA4),
35       mSamples(0),
36       mMultisamplingMode(MultisamplingMode::Regular),
37       mInitState(InitState::Initialized)
38 {}
39 
~RenderbufferState()40 RenderbufferState::~RenderbufferState() {}
41 
getWidth() const42 GLsizei RenderbufferState::getWidth() const
43 {
44     return mWidth;
45 }
46 
getHeight() const47 GLsizei RenderbufferState::getHeight() const
48 {
49     return mHeight;
50 }
51 
getFormat() const52 const Format &RenderbufferState::getFormat() const
53 {
54     return mFormat;
55 }
56 
getSamples() const57 GLsizei RenderbufferState::getSamples() const
58 {
59     return mSamples;
60 }
61 
getMultisamplingMode() const62 MultisamplingMode RenderbufferState::getMultisamplingMode() const
63 {
64     return mMultisamplingMode;
65 }
66 
getInitState() const67 InitState RenderbufferState::getInitState() const
68 {
69     return mInitState;
70 }
71 
update(GLsizei width,GLsizei height,const Format & format,GLsizei samples,MultisamplingMode multisamplingMode,InitState initState)72 void RenderbufferState::update(GLsizei width,
73                                GLsizei height,
74                                const Format &format,
75                                GLsizei samples,
76                                MultisamplingMode multisamplingMode,
77                                InitState initState)
78 {
79     mWidth             = width;
80     mHeight            = height;
81     mFormat            = format;
82     mSamples           = samples;
83     mMultisamplingMode = multisamplingMode;
84     mInitState         = InitState::MayNeedInit;
85 }
86 
87 // Renderbuffer implementation.
Renderbuffer(rx::GLImplFactory * implFactory,RenderbufferID id)88 Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id)
89     : RefCountObject(implFactory->generateSerial(), id),
90       mState(),
91       mImplementation(implFactory->createRenderbuffer(mState)),
92       mLabel(),
93       mImplObserverBinding(this, kRenderbufferImplSubjectIndex)
94 {
95     mImplObserverBinding.bind(mImplementation.get());
96 }
97 
onDestroy(const Context * context)98 void Renderbuffer::onDestroy(const Context *context)
99 {
100     (void)(orphanImages(context));
101 
102     if (mImplementation)
103     {
104         mImplementation->onDestroy(context);
105     }
106 }
107 
~Renderbuffer()108 Renderbuffer::~Renderbuffer() {}
109 
setLabel(const Context * context,const std::string & label)110 void Renderbuffer::setLabel(const Context *context, const std::string &label)
111 {
112     mLabel = label;
113 }
114 
getLabel() const115 const std::string &Renderbuffer::getLabel() const
116 {
117     return mLabel;
118 }
119 
setStorage(const Context * context,GLenum internalformat,GLsizei width,GLsizei height)120 angle::Result Renderbuffer::setStorage(const Context *context,
121                                        GLenum internalformat,
122                                        GLsizei width,
123                                        GLsizei height)
124 {
125     ANGLE_TRY(orphanImages(context));
126     ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height));
127 
128     mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular,
129                   InitState::MayNeedInit);
130     onStateChange(angle::SubjectMessage::SubjectChanged);
131 
132     return angle::Result::Continue;
133 }
134 
setStorageMultisample(const Context * context,GLsizei samplesIn,GLenum internalformat,GLsizei width,GLsizei height,MultisamplingMode mode)135 angle::Result Renderbuffer::setStorageMultisample(const Context *context,
136                                                   GLsizei samplesIn,
137                                                   GLenum internalformat,
138                                                   GLsizei width,
139                                                   GLsizei height,
140                                                   MultisamplingMode mode)
141 {
142     ANGLE_TRY(orphanImages(context));
143 
144     // Potentially adjust "samplesIn" to a supported value
145     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
146     GLsizei samples               = formatCaps.getNearestSamples(samplesIn);
147 
148     ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width,
149                                                      height, mode));
150 
151     mState.update(width, height, Format(internalformat), samples, mode, InitState::MayNeedInit);
152     onStateChange(angle::SubjectMessage::SubjectChanged);
153 
154     return angle::Result::Continue;
155 }
156 
setStorageEGLImageTarget(const Context * context,egl::Image * image)157 angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
158 {
159     ANGLE_TRY(orphanImages(context));
160     ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image));
161 
162     setTargetImage(context, image);
163 
164     mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
165                   Format(image->getFormat()), 0, MultisamplingMode::Regular,
166                   image->sourceInitState());
167     onStateChange(angle::SubjectMessage::SubjectChanged);
168 
169     return angle::Result::Continue;
170 }
171 
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)172 angle::Result Renderbuffer::copyRenderbufferSubData(Context *context,
173                                                     const gl::Renderbuffer *srcBuffer,
174                                                     GLint srcLevel,
175                                                     GLint srcX,
176                                                     GLint srcY,
177                                                     GLint srcZ,
178                                                     GLint dstLevel,
179                                                     GLint dstX,
180                                                     GLint dstY,
181                                                     GLint dstZ,
182                                                     GLsizei srcWidth,
183                                                     GLsizei srcHeight,
184                                                     GLsizei srcDepth)
185 {
186     ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY,
187                                                        srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
188                                                        srcHeight, srcDepth));
189 
190     return angle::Result::Continue;
191 }
192 
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)193 angle::Result Renderbuffer::copyTextureSubData(Context *context,
194                                                const gl::Texture *srcTexture,
195                                                GLint srcLevel,
196                                                GLint srcX,
197                                                GLint srcY,
198                                                GLint srcZ,
199                                                GLint dstLevel,
200                                                GLint dstX,
201                                                GLint dstY,
202                                                GLint dstZ,
203                                                GLsizei srcWidth,
204                                                GLsizei srcHeight,
205                                                GLsizei srcDepth)
206 {
207     ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
208                                                   dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
209                                                   srcDepth));
210 
211     return angle::Result::Continue;
212 }
213 
getImplementation() const214 rx::RenderbufferImpl *Renderbuffer::getImplementation() const
215 {
216     ASSERT(mImplementation);
217     return mImplementation.get();
218 }
219 
getWidth() const220 GLsizei Renderbuffer::getWidth() const
221 {
222     return mState.mWidth;
223 }
224 
getHeight() const225 GLsizei Renderbuffer::getHeight() const
226 {
227     return mState.mHeight;
228 }
229 
getFormat() const230 const Format &Renderbuffer::getFormat() const
231 {
232     return mState.mFormat;
233 }
234 
getSamples() const235 GLsizei Renderbuffer::getSamples() const
236 {
237     return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0;
238 }
239 
getMultisamplingMode() const240 MultisamplingMode Renderbuffer::getMultisamplingMode() const
241 {
242     return mState.mMultisamplingMode;
243 }
244 
getRedSize() const245 GLuint Renderbuffer::getRedSize() const
246 {
247     return mState.mFormat.info->redBits;
248 }
249 
getGreenSize() const250 GLuint Renderbuffer::getGreenSize() const
251 {
252     return mState.mFormat.info->greenBits;
253 }
254 
getBlueSize() const255 GLuint Renderbuffer::getBlueSize() const
256 {
257     return mState.mFormat.info->blueBits;
258 }
259 
getAlphaSize() const260 GLuint Renderbuffer::getAlphaSize() const
261 {
262     return mState.mFormat.info->alphaBits;
263 }
264 
getDepthSize() const265 GLuint Renderbuffer::getDepthSize() const
266 {
267     return mState.mFormat.info->depthBits;
268 }
269 
getStencilSize() const270 GLuint Renderbuffer::getStencilSize() const
271 {
272     return mState.mFormat.info->stencilBits;
273 }
274 
getState() const275 const RenderbufferState &Renderbuffer::getState() const
276 {
277     return mState;
278 }
279 
getMemorySize() const280 GLint Renderbuffer::getMemorySize() const
281 {
282     GLint implSize = mImplementation->getMemorySize();
283     if (implSize > 0)
284     {
285         return implSize;
286     }
287 
288     // Assume allocated size is around width * height * samples * pixelBytes
289     angle::CheckedNumeric<GLint> size = 1;
290     size *= mState.mFormat.info->pixelBytes;
291     size *= mState.mWidth;
292     size *= mState.mHeight;
293     size *= std::max(mState.mSamples, 1);
294     return size.ValueOrDefault(std::numeric_limits<GLint>::max());
295 }
296 
onAttach(const Context * context,rx::Serial framebufferSerial)297 void Renderbuffer::onAttach(const Context *context, rx::Serial framebufferSerial)
298 {
299     addRef();
300 }
301 
onDetach(const Context * context,rx::Serial framebufferSerial)302 void Renderbuffer::onDetach(const Context *context, rx::Serial framebufferSerial)
303 {
304     release(context);
305 }
306 
getId() const307 GLuint Renderbuffer::getId() const
308 {
309     return id().value;
310 }
311 
getAttachmentSize(const gl::ImageIndex &) const312 Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
313 {
314     return Extents(mState.mWidth, mState.mHeight, 1);
315 }
316 
getAttachmentFormat(GLenum,const ImageIndex &) const317 Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
318                                          const ImageIndex & /*imageIndex*/) const
319 {
320     return getFormat();
321 }
getAttachmentSamples(const ImageIndex &) const322 GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
323 {
324     return getSamples();
325 }
326 
isRenderable(const Context * context,GLenum binding,const ImageIndex & imageIndex) const327 bool Renderbuffer::isRenderable(const Context *context,
328                                 GLenum binding,
329                                 const ImageIndex &imageIndex) const
330 {
331     if (isEGLImageTarget())
332     {
333         return ImageSibling::isRenderable(context, binding, imageIndex);
334     }
335     return getFormat().info->renderbufferSupport(context->getClientVersion(),
336                                                  context->getExtensions());
337 }
338 
initState(const gl::ImageIndex &) const339 InitState Renderbuffer::initState(const gl::ImageIndex & /*imageIndex*/) const
340 {
341     if (isEGLImageTarget())
342     {
343         return sourceEGLImageInitState();
344     }
345 
346     return mState.mInitState;
347 }
348 
setInitState(const gl::ImageIndex &,InitState initState)349 void Renderbuffer::setInitState(const gl::ImageIndex & /*imageIndex*/, InitState initState)
350 {
351     if (isEGLImageTarget())
352     {
353         setSourceEGLImageInitState(initState);
354     }
355     else
356     {
357         mState.mInitState = initState;
358     }
359 }
360 
getAttachmentImpl() const361 rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
362 {
363     return mImplementation.get();
364 }
365 
getImplementationColorReadFormat(const Context * context) const366 GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
367 {
368     return mImplementation->getColorReadFormat(context);
369 }
370 
getImplementationColorReadType(const Context * context) const371 GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
372 {
373     return mImplementation->getColorReadType(context);
374 }
375 
getRenderbufferImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,GLenum format,GLenum type,void * pixels) const376 angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
377                                                  const PixelPackState &packState,
378                                                  Buffer *packBuffer,
379                                                  GLenum format,
380                                                  GLenum type,
381                                                  void *pixels) const
382 {
383     return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
384                                                  pixels);
385 }
386 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)387 void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
388 {
389     ASSERT(message == angle::SubjectMessage::SubjectChanged);
390     onStateChange(angle::SubjectMessage::ContentsChanged);
391 }
392 }  // namespace gl
393