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