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
DetermineInitState(const Context * context)29 InitState DetermineInitState(const Context *context)
30 {
31 return (context && context->isRobustResourceInitEnabled()) ? InitState::MayNeedInit
32 : InitState::Initialized;
33 }
34 } // namespace
35
36 // RenderbufferState implementation.
RenderbufferState()37 RenderbufferState::RenderbufferState()
38 : mWidth(0),
39 mHeight(0),
40 mFormat(GL_RGBA4),
41 mSamples(0),
42 mMultisamplingMode(MultisamplingMode::Regular),
43 mHasProtectedContent(false),
44 mInitState(InitState::Initialized)
45 {}
46
~RenderbufferState()47 RenderbufferState::~RenderbufferState() {}
48
getWidth() const49 GLsizei RenderbufferState::getWidth() const
50 {
51 return mWidth;
52 }
53
getHeight() const54 GLsizei RenderbufferState::getHeight() const
55 {
56 return mHeight;
57 }
58
getFormat() const59 const Format &RenderbufferState::getFormat() const
60 {
61 return mFormat;
62 }
63
getSamples() const64 GLsizei RenderbufferState::getSamples() const
65 {
66 return mSamples;
67 }
68
getMultisamplingMode() const69 MultisamplingMode RenderbufferState::getMultisamplingMode() const
70 {
71 return mMultisamplingMode;
72 }
73
getInitState() const74 InitState RenderbufferState::getInitState() const
75 {
76 return mInitState;
77 }
78
update(GLsizei width,GLsizei height,const Format & format,GLsizei samples,MultisamplingMode multisamplingMode,InitState initState)79 void RenderbufferState::update(GLsizei width,
80 GLsizei height,
81 const Format &format,
82 GLsizei samples,
83 MultisamplingMode multisamplingMode,
84 InitState initState)
85 {
86 mWidth = width;
87 mHeight = height;
88 mFormat = format;
89 mSamples = samples;
90 mMultisamplingMode = multisamplingMode;
91 mInitState = initState;
92 mHasProtectedContent = false;
93 }
94
setProtectedContent(bool hasProtectedContent)95 void RenderbufferState::setProtectedContent(bool hasProtectedContent)
96 {
97 mHasProtectedContent = hasProtectedContent;
98 }
99
100 // Renderbuffer implementation.
Renderbuffer(rx::GLImplFactory * implFactory,RenderbufferID id)101 Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id)
102 : RefCountObject(implFactory->generateSerial(), id),
103 mState(),
104 mImplementation(implFactory->createRenderbuffer(mState)),
105 mLabel(),
106 mImplObserverBinding(this, kRenderbufferImplSubjectIndex)
107 {
108 mImplObserverBinding.bind(mImplementation.get());
109 }
110
onDestroy(const Context * context)111 void Renderbuffer::onDestroy(const Context *context)
112 {
113 egl::RefCountObjectReleaser<egl::Image> releaseImage;
114 (void)orphanImages(context, &releaseImage);
115
116 if (mImplementation)
117 {
118 mImplementation->onDestroy(context);
119 }
120 }
121
~Renderbuffer()122 Renderbuffer::~Renderbuffer() {}
123
setLabel(const Context * context,const std::string & label)124 angle::Result Renderbuffer::setLabel(const Context *context, const std::string &label)
125 {
126 mLabel = label;
127
128 if (mImplementation)
129 {
130 return mImplementation->onLabelUpdate(context);
131 }
132 return angle::Result::Continue;
133 }
134
getLabel() const135 const std::string &Renderbuffer::getLabel() const
136 {
137 return mLabel;
138 }
139
setStorage(const Context * context,GLenum internalformat,GLsizei width,GLsizei height)140 angle::Result Renderbuffer::setStorage(const Context *context,
141 GLenum internalformat,
142 GLsizei width,
143 GLsizei height)
144 {
145
146 egl::RefCountObjectReleaser<egl::Image> releaseImage;
147 ANGLE_TRY(orphanImages(context, &releaseImage));
148
149 ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height));
150
151 mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular,
152 DetermineInitState(context));
153 onStateChange(angle::SubjectMessage::SubjectChanged);
154
155 return angle::Result::Continue;
156 }
157
setStorageMultisample(const Context * context,GLsizei samplesIn,GLenum internalformat,GLsizei width,GLsizei height,MultisamplingMode mode)158 angle::Result Renderbuffer::setStorageMultisample(const Context *context,
159 GLsizei samplesIn,
160 GLenum internalformat,
161 GLsizei width,
162 GLsizei height,
163 MultisamplingMode mode)
164 {
165 egl::RefCountObjectReleaser<egl::Image> releaseImage;
166 ANGLE_TRY(orphanImages(context, &releaseImage));
167
168 // Potentially adjust "samplesIn" to a supported value
169 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
170 GLsizei samples = formatCaps.getNearestSamples(samplesIn);
171
172 ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width,
173 height, mode));
174
175 mState.update(width, height, Format(internalformat), samples, mode,
176 DetermineInitState(context));
177 onStateChange(angle::SubjectMessage::SubjectChanged);
178
179 return angle::Result::Continue;
180 }
181
setStorageEGLImageTarget(const Context * context,egl::Image * image)182 angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
183 {
184 egl::RefCountObjectReleaser<egl::Image> releaseImage;
185 ANGLE_TRY(orphanImages(context, &releaseImage));
186
187 ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image));
188
189 setTargetImage(context, image);
190
191 mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
192 Format(image->getFormat()), 0, MultisamplingMode::Regular,
193 image->sourceInitState());
194 mState.setProtectedContent(image->hasProtectedContent());
195
196 onStateChange(angle::SubjectMessage::SubjectChanged);
197
198 return angle::Result::Continue;
199 }
200
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)201 angle::Result Renderbuffer::copyRenderbufferSubData(Context *context,
202 const gl::Renderbuffer *srcBuffer,
203 GLint srcLevel,
204 GLint srcX,
205 GLint srcY,
206 GLint srcZ,
207 GLint dstLevel,
208 GLint dstX,
209 GLint dstY,
210 GLint dstZ,
211 GLsizei srcWidth,
212 GLsizei srcHeight,
213 GLsizei srcDepth)
214 {
215 ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY,
216 srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
217 srcHeight, srcDepth));
218
219 return angle::Result::Continue;
220 }
221
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)222 angle::Result Renderbuffer::copyTextureSubData(Context *context,
223 const gl::Texture *srcTexture,
224 GLint srcLevel,
225 GLint srcX,
226 GLint srcY,
227 GLint srcZ,
228 GLint dstLevel,
229 GLint dstX,
230 GLint dstY,
231 GLint dstZ,
232 GLsizei srcWidth,
233 GLsizei srcHeight,
234 GLsizei srcDepth)
235 {
236 ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
237 dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
238 srcDepth));
239
240 return angle::Result::Continue;
241 }
242
getImplementation() const243 rx::RenderbufferImpl *Renderbuffer::getImplementation() const
244 {
245 ASSERT(mImplementation);
246 return mImplementation.get();
247 }
248
getWidth() const249 GLsizei Renderbuffer::getWidth() const
250 {
251 return mState.mWidth;
252 }
253
getHeight() const254 GLsizei Renderbuffer::getHeight() const
255 {
256 return mState.mHeight;
257 }
258
getFormat() const259 const Format &Renderbuffer::getFormat() const
260 {
261 return mState.mFormat;
262 }
263
getSamples() const264 GLsizei Renderbuffer::getSamples() const
265 {
266 return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0;
267 }
268
getMultisamplingMode() const269 MultisamplingMode Renderbuffer::getMultisamplingMode() const
270 {
271 return mState.mMultisamplingMode;
272 }
273
getRedSize() const274 GLuint Renderbuffer::getRedSize() const
275 {
276 return mState.mFormat.info->redBits;
277 }
278
getGreenSize() const279 GLuint Renderbuffer::getGreenSize() const
280 {
281 return mState.mFormat.info->greenBits;
282 }
283
getBlueSize() const284 GLuint Renderbuffer::getBlueSize() const
285 {
286 return mState.mFormat.info->blueBits;
287 }
288
getAlphaSize() const289 GLuint Renderbuffer::getAlphaSize() const
290 {
291 return mState.mFormat.info->alphaBits;
292 }
293
getDepthSize() const294 GLuint Renderbuffer::getDepthSize() const
295 {
296 return mState.mFormat.info->depthBits;
297 }
298
getStencilSize() const299 GLuint Renderbuffer::getStencilSize() const
300 {
301 return mState.mFormat.info->stencilBits;
302 }
303
getState() const304 const RenderbufferState &Renderbuffer::getState() const
305 {
306 return mState;
307 }
308
getMemorySize() const309 GLint Renderbuffer::getMemorySize() const
310 {
311 GLint implSize = mImplementation->getMemorySize();
312 if (implSize > 0)
313 {
314 return implSize;
315 }
316
317 // Assume allocated size is around width * height * samples * pixelBytes
318 angle::CheckedNumeric<GLint> size = 1;
319 size *= mState.mFormat.info->pixelBytes;
320 size *= mState.mWidth;
321 size *= mState.mHeight;
322 size *= std::max(mState.mSamples, 1);
323 return size.ValueOrDefault(std::numeric_limits<GLint>::max());
324 }
325
onAttach(const Context * context,rx::UniqueSerial framebufferSerial)326 void Renderbuffer::onAttach(const Context *context, rx::UniqueSerial framebufferSerial)
327 {
328 addRef();
329 }
330
onDetach(const Context * context,rx::UniqueSerial framebufferSerial)331 void Renderbuffer::onDetach(const Context *context, rx::UniqueSerial framebufferSerial)
332 {
333 release(context);
334 }
335
getId() const336 GLuint Renderbuffer::getId() const
337 {
338 return id().value;
339 }
340
getAttachmentSize(const gl::ImageIndex &) const341 Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
342 {
343 return Extents(mState.mWidth, mState.mHeight, 1);
344 }
345
getAttachmentFormat(GLenum,const ImageIndex &) const346 Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
347 const ImageIndex & /*imageIndex*/) const
348 {
349 return getFormat();
350 }
getAttachmentSamples(const ImageIndex &) const351 GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
352 {
353 return getSamples();
354 }
355
isRenderable(const Context * context,GLenum binding,const ImageIndex & imageIndex) const356 bool Renderbuffer::isRenderable(const Context *context,
357 GLenum binding,
358 const ImageIndex &imageIndex) const
359 {
360 if (isEGLImageTarget())
361 {
362 return ImageSibling::isRenderable(context, binding, imageIndex);
363 }
364 return getFormat().info->renderbufferSupport(context->getClientVersion(),
365 context->getExtensions());
366 }
367
initState(GLenum,const gl::ImageIndex &) const368 InitState Renderbuffer::initState(GLenum /*binding*/, const gl::ImageIndex & /*imageIndex*/) const
369 {
370 if (isEGLImageTarget())
371 {
372 return sourceEGLImageInitState();
373 }
374
375 return mState.mInitState;
376 }
377
setInitState(GLenum,const gl::ImageIndex &,InitState initState)378 void Renderbuffer::setInitState(GLenum /*binding*/,
379 const gl::ImageIndex & /*imageIndex*/,
380 InitState initState)
381 {
382 if (isEGLImageTarget())
383 {
384 setSourceEGLImageInitState(initState);
385 }
386 else
387 {
388 mState.mInitState = initState;
389 }
390 }
391
getAttachmentImpl() const392 rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
393 {
394 return mImplementation.get();
395 }
396
getImplementationColorReadFormat(const Context * context) const397 GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
398 {
399 return mImplementation->getColorReadFormat(context);
400 }
401
getImplementationColorReadType(const Context * context) const402 GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
403 {
404 return mImplementation->getColorReadType(context);
405 }
406
getRenderbufferImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,GLenum format,GLenum type,void * pixels) const407 angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
408 const PixelPackState &packState,
409 Buffer *packBuffer,
410 GLenum format,
411 GLenum type,
412 void *pixels) const
413 {
414 return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
415 pixels);
416 }
417
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)418 void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
419 {
420 ASSERT(message == angle::SubjectMessage::SubjectChanged);
421 onStateChange(angle::SubjectMessage::ContentsChanged);
422 }
423 } // namespace gl
424