• 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), mHeight(0), mFormat(GL_RGBA4), mSamples(0), mInitState(InitState::MayNeedInit)
33 {}
34 
~RenderbufferState()35 RenderbufferState::~RenderbufferState() {}
36 
getWidth() const37 GLsizei RenderbufferState::getWidth() const
38 {
39     return mWidth;
40 }
41 
getHeight() const42 GLsizei RenderbufferState::getHeight() const
43 {
44     return mHeight;
45 }
46 
getFormat() const47 const Format &RenderbufferState::getFormat() const
48 {
49     return mFormat;
50 }
51 
getSamples() const52 GLsizei RenderbufferState::getSamples() const
53 {
54     return mSamples;
55 }
56 
update(GLsizei width,GLsizei height,const Format & format,GLsizei samples,InitState initState)57 void RenderbufferState::update(GLsizei width,
58                                GLsizei height,
59                                const Format &format,
60                                GLsizei samples,
61                                InitState initState)
62 {
63     mWidth     = static_cast<GLsizei>(width);
64     mHeight    = static_cast<GLsizei>(height);
65     mFormat    = format;
66     mSamples   = samples;
67     mInitState = InitState::MayNeedInit;
68 }
69 
70 // Renderbuffer implementation.
Renderbuffer(rx::GLImplFactory * implFactory,RenderbufferID id)71 Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id)
72     : RefCountObject(implFactory->generateSerial(), id),
73       mState(),
74       mImplementation(implFactory->createRenderbuffer(mState)),
75       mLabel(),
76       mImplObserverBinding(this, kRenderbufferImplSubjectIndex)
77 {
78     mImplObserverBinding.bind(mImplementation.get());
79 }
80 
onDestroy(const Context * context)81 void Renderbuffer::onDestroy(const Context *context)
82 {
83     (void)(orphanImages(context));
84 
85     if (mImplementation)
86     {
87         mImplementation->onDestroy(context);
88     }
89 }
90 
~Renderbuffer()91 Renderbuffer::~Renderbuffer() {}
92 
setLabel(const Context * context,const std::string & label)93 void Renderbuffer::setLabel(const Context *context, const std::string &label)
94 {
95     mLabel = label;
96 }
97 
getLabel() const98 const std::string &Renderbuffer::getLabel() const
99 {
100     return mLabel;
101 }
102 
setStorage(const Context * context,GLenum internalformat,size_t width,size_t height)103 angle::Result Renderbuffer::setStorage(const Context *context,
104                                        GLenum internalformat,
105                                        size_t width,
106                                        size_t height)
107 {
108     ANGLE_TRY(orphanImages(context));
109     ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height));
110 
111     mState.update(static_cast<GLsizei>(width), static_cast<GLsizei>(height), Format(internalformat),
112                   0, InitState::MayNeedInit);
113     onStateChange(angle::SubjectMessage::SubjectChanged);
114 
115     return angle::Result::Continue;
116 }
117 
setStorageMultisample(const Context * context,size_t samples,GLenum internalformat,size_t width,size_t height)118 angle::Result Renderbuffer::setStorageMultisample(const Context *context,
119                                                   size_t samples,
120                                                   GLenum internalformat,
121                                                   size_t width,
122                                                   size_t height)
123 {
124     ANGLE_TRY(orphanImages(context));
125 
126     // Potentially adjust "samples" to a supported value
127     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
128     samples                       = formatCaps.getNearestSamples(static_cast<GLuint>(samples));
129 
130     ANGLE_TRY(
131         mImplementation->setStorageMultisample(context, samples, internalformat, width, height));
132 
133     mState.update(static_cast<GLsizei>(width), static_cast<GLsizei>(height), Format(internalformat),
134                   static_cast<GLsizei>(samples), InitState::MayNeedInit);
135     onStateChange(angle::SubjectMessage::SubjectChanged);
136 
137     return angle::Result::Continue;
138 }
139 
setStorageEGLImageTarget(const Context * context,egl::Image * image)140 angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
141 {
142     ANGLE_TRY(orphanImages(context));
143     ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image));
144 
145     setTargetImage(context, image);
146 
147     mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
148                   Format(image->getFormat()), 0, image->sourceInitState());
149     onStateChange(angle::SubjectMessage::SubjectChanged);
150 
151     return angle::Result::Continue;
152 }
153 
getImplementation() const154 rx::RenderbufferImpl *Renderbuffer::getImplementation() const
155 {
156     ASSERT(mImplementation);
157     return mImplementation.get();
158 }
159 
getWidth() const160 GLsizei Renderbuffer::getWidth() const
161 {
162     return mState.mWidth;
163 }
164 
getHeight() const165 GLsizei Renderbuffer::getHeight() const
166 {
167     return mState.mHeight;
168 }
169 
getFormat() const170 const Format &Renderbuffer::getFormat() const
171 {
172     return mState.mFormat;
173 }
174 
getSamples() const175 GLsizei Renderbuffer::getSamples() const
176 {
177     return mState.mSamples;
178 }
179 
getRedSize() const180 GLuint Renderbuffer::getRedSize() const
181 {
182     return mState.mFormat.info->redBits;
183 }
184 
getGreenSize() const185 GLuint Renderbuffer::getGreenSize() const
186 {
187     return mState.mFormat.info->greenBits;
188 }
189 
getBlueSize() const190 GLuint Renderbuffer::getBlueSize() const
191 {
192     return mState.mFormat.info->blueBits;
193 }
194 
getAlphaSize() const195 GLuint Renderbuffer::getAlphaSize() const
196 {
197     return mState.mFormat.info->alphaBits;
198 }
199 
getDepthSize() const200 GLuint Renderbuffer::getDepthSize() const
201 {
202     return mState.mFormat.info->depthBits;
203 }
204 
getStencilSize() const205 GLuint Renderbuffer::getStencilSize() const
206 {
207     return mState.mFormat.info->stencilBits;
208 }
209 
getMemorySize() const210 GLint Renderbuffer::getMemorySize() const
211 {
212     GLint implSize = mImplementation->getMemorySize();
213     if (implSize > 0)
214     {
215         return implSize;
216     }
217 
218     // Assume allocated size is around width * height * samples * pixelBytes
219     angle::CheckedNumeric<GLint> size = 1;
220     size *= mState.mFormat.info->pixelBytes;
221     size *= mState.mWidth;
222     size *= mState.mHeight;
223     size *= std::max(mState.mSamples, 1);
224     return size.ValueOrDefault(std::numeric_limits<GLint>::max());
225 }
226 
onAttach(const Context * context)227 void Renderbuffer::onAttach(const Context *context)
228 {
229     addRef();
230 }
231 
onDetach(const Context * context)232 void Renderbuffer::onDetach(const Context *context)
233 {
234     release(context);
235 }
236 
getId() const237 GLuint Renderbuffer::getId() const
238 {
239     return id().value;
240 }
241 
getAttachmentSize(const gl::ImageIndex &) const242 Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
243 {
244     return Extents(mState.mWidth, mState.mHeight, 1);
245 }
246 
getAttachmentFormat(GLenum,const ImageIndex &) const247 Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
248                                          const ImageIndex & /*imageIndex*/) const
249 {
250     return getFormat();
251 }
getAttachmentSamples(const ImageIndex &) const252 GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
253 {
254     return getSamples();
255 }
256 
isRenderable(const Context * context,GLenum binding,const ImageIndex & imageIndex) const257 bool Renderbuffer::isRenderable(const Context *context,
258                                 GLenum binding,
259                                 const ImageIndex &imageIndex) const
260 {
261     if (isEGLImageTarget())
262     {
263         return ImageSibling::isRenderable(context, binding, imageIndex);
264     }
265     return getFormat().info->renderbufferSupport(context->getClientVersion(),
266                                                  context->getExtensions());
267 }
268 
initState(const gl::ImageIndex &) const269 InitState Renderbuffer::initState(const gl::ImageIndex & /*imageIndex*/) const
270 {
271     if (isEGLImageTarget())
272     {
273         return sourceEGLImageInitState();
274     }
275 
276     return mState.mInitState;
277 }
278 
setInitState(const gl::ImageIndex &,InitState initState)279 void Renderbuffer::setInitState(const gl::ImageIndex & /*imageIndex*/, InitState initState)
280 {
281     if (isEGLImageTarget())
282     {
283         setSourceEGLImageInitState(initState);
284     }
285     else
286     {
287         mState.mInitState = initState;
288     }
289 }
290 
getAttachmentImpl() const291 rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
292 {
293     return mImplementation.get();
294 }
295 
getImplementationColorReadFormat(const Context * context) const296 GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
297 {
298     return mImplementation->getColorReadFormat(context);
299 }
300 
getImplementationColorReadType(const Context * context) const301 GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
302 {
303     return mImplementation->getColorReadType(context);
304 }
305 
getRenderbufferImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,GLenum format,GLenum type,void * pixels) const306 angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
307                                                  const PixelPackState &packState,
308                                                  Buffer *packBuffer,
309                                                  GLenum format,
310                                                  GLenum type,
311                                                  void *pixels) const
312 {
313     return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
314                                                  pixels);
315 }
316 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)317 void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
318 {
319     ASSERT(message == angle::SubjectMessage::SubjectChanged);
320     onStateChange(angle::SubjectMessage::ContentsChanged);
321 }
322 }  // namespace gl
323