2 * Mesa 3-D graphics library
4 * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
33 #include "framebuffer.h"
40 * Create a texture image that wraps a renderbuffer.
42 static struct gl_texture_image
*
43 wrap_renderbuffer(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
)
46 struct gl_texture_object
*texObj
;
47 struct gl_texture_image
*texImage
;
49 if (rb
->NumSamples
> 1)
50 texTarget
= GL_TEXTURE_2D_MULTISAMPLE
;
52 texTarget
= GL_TEXTURE_2D
;
54 /* Texture ID is not significant since it never goes into the hash table */
55 texObj
= ctx
->Driver
.NewTextureObject(ctx
, 0, texTarget
);
60 texImage
= _mesa_get_tex_image(ctx
, texObj
, texTarget
, 0);
65 if (!ctx
->Driver
.BindRenderbufferTexImage(ctx
, rb
, texImage
)) {
66 _mesa_problem(ctx
, "Failed to create texture from renderbuffer");
70 if (ctx
->Driver
.FinishRenderTexture
&& !rb
->NeedsFinishRenderTexture
) {
71 rb
->NeedsFinishRenderTexture
= true;
72 ctx
->Driver
.FinishRenderTexture(ctx
, rb
);
79 /* This function makes a texture view without bothering with all of the API
80 * checks. Most of them are the same for CopyTexSubImage so checking would
81 * be redundant. The one major difference is that we don't check for
82 * whether the texture is immutable or not. However, since the view will
83 * be created and then immediately destroyed, this should not be a problem.
86 make_view(struct gl_context
*ctx
, struct gl_texture_image
*tex_image
,
87 struct gl_texture_image
**view_tex_image
, GLuint
*view_tex_name
,
88 GLenum internal_format
)
90 struct gl_texture_object
*tex_obj
= tex_image
->TexObject
;
91 struct gl_texture_object
*view_tex_obj
;
92 mesa_format tex_format
;
94 /* Set up the new texture object */
95 _mesa_GenTextures(1, view_tex_name
);
96 view_tex_obj
= _mesa_lookup_texture(ctx
, *view_tex_name
);
100 tex_format
= _mesa_choose_texture_format(ctx
, view_tex_obj
, tex_obj
->Target
,
104 if (!ctx
->Driver
.TestProxyTexImage(ctx
, tex_obj
->Target
, 1, 0, tex_format
,
105 1, tex_image
->Width
, tex_image
->Height
,
107 _mesa_DeleteTextures(1, view_tex_name
);
112 assert(tex_obj
->Target
!= 0);
113 assert(tex_obj
->TargetIndex
< NUM_TEXTURE_TARGETS
);
115 view_tex_obj
->Target
= tex_obj
->Target
;
116 view_tex_obj
->TargetIndex
= tex_obj
->TargetIndex
;
118 *view_tex_image
= _mesa_get_tex_image(ctx
, view_tex_obj
, tex_obj
->Target
, 0);
120 if (!*view_tex_image
) {
121 _mesa_DeleteTextures(1, view_tex_name
);
126 _mesa_init_teximage_fields(ctx
, *view_tex_image
,
127 tex_image
->Width
, tex_image
->Height
,
129 0, internal_format
, tex_format
);
131 view_tex_obj
->MinLevel
= tex_image
->Level
;
132 view_tex_obj
->NumLevels
= 1;
133 view_tex_obj
->MinLayer
= tex_obj
->MinLayer
;
134 view_tex_obj
->NumLayers
= tex_obj
->NumLayers
;
135 view_tex_obj
->Immutable
= tex_obj
->Immutable
;
136 view_tex_obj
->ImmutableLevels
= tex_obj
->ImmutableLevels
;
138 if (ctx
->Driver
.TextureView
!= NULL
&&
139 !ctx
->Driver
.TextureView(ctx
, view_tex_obj
, tex_obj
)) {
140 _mesa_DeleteTextures(1, view_tex_name
);
142 return false; /* driver recorded error */
148 /** A partial implementation of glCopyImageSubData
150 * This is a partial implementation of glCopyImageSubData that works only
151 * if both textures are uncompressed and the destination texture is
152 * renderable. It uses a slight abuse of a texture view (see make_view) to
153 * turn the source texture into the destination texture type and then uses
154 * _mesa_meta_BlitFramebuffers to do the copy.
157 _mesa_meta_CopyImageSubData_uncompressed(struct gl_context
*ctx
,
158 struct gl_texture_image
*src_tex_image
,
159 struct gl_renderbuffer
*src_renderbuffer
,
160 int src_x
, int src_y
, int src_z
,
161 struct gl_texture_image
*dst_tex_image
,
162 struct gl_renderbuffer
*dst_renderbuffer
,
163 int dst_x
, int dst_y
, int dst_z
,
164 int src_width
, int src_height
)
166 mesa_format src_format
, dst_format
;
167 GLint src_internal_format
, dst_internal_format
;
168 GLuint src_view_texture
= 0;
169 struct gl_texture_image
*src_view_tex_image
;
170 struct gl_framebuffer
*readFb
;
171 struct gl_framebuffer
*drawFb
= NULL
;
172 bool success
= false;
174 GLenum status
, attachment
;
176 if (src_renderbuffer
) {
177 src_format
= src_renderbuffer
->Format
;
178 src_internal_format
= src_renderbuffer
->InternalFormat
;
180 assert(src_tex_image
);
181 src_format
= src_tex_image
->TexFormat
;
182 src_internal_format
= src_tex_image
->InternalFormat
;
185 if (dst_renderbuffer
) {
186 dst_format
= dst_renderbuffer
->Format
;
187 dst_internal_format
= dst_renderbuffer
->InternalFormat
;
189 assert(dst_tex_image
);
190 dst_format
= dst_tex_image
->TexFormat
;
191 dst_internal_format
= dst_tex_image
->InternalFormat
;
194 if (_mesa_is_format_compressed(src_format
))
197 if (_mesa_is_format_compressed(dst_format
))
200 if (src_internal_format
== dst_internal_format
) {
201 src_view_tex_image
= src_tex_image
;
203 if (src_renderbuffer
) {
204 assert(src_tex_image
== NULL
);
205 src_tex_image
= wrap_renderbuffer(ctx
, src_renderbuffer
);
207 if (!make_view(ctx
, src_tex_image
, &src_view_tex_image
, &src_view_texture
,
208 dst_internal_format
))
212 /* We really only need to stash the bound framebuffers and scissor. */
213 _mesa_meta_begin(ctx
, MESA_META_SCISSOR
);
215 readFb
= ctx
->Driver
.NewFramebuffer(ctx
, 0xDEADBEEF);
219 drawFb
= ctx
->Driver
.NewFramebuffer(ctx
, 0xDEADBEEF);
223 _mesa_bind_framebuffers(ctx
, drawFb
, readFb
);
225 switch (_mesa_get_format_base_format(src_format
)) {
226 case GL_DEPTH_COMPONENT
:
227 attachment
= GL_DEPTH_ATTACHMENT
;
228 mask
= GL_DEPTH_BUFFER_BIT
;
230 case GL_DEPTH_STENCIL
:
231 attachment
= GL_DEPTH_STENCIL_ATTACHMENT
;
232 mask
= GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
;
234 case GL_STENCIL_INDEX
:
235 attachment
= GL_STENCIL_ATTACHMENT
;
236 mask
= GL_STENCIL_BUFFER_BIT
;
239 attachment
= GL_COLOR_ATTACHMENT0
;
240 mask
= GL_COLOR_BUFFER_BIT
;
241 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0
);
242 _mesa_ReadBuffer(GL_COLOR_ATTACHMENT0
);
245 if (src_view_tex_image
) {
246 /* Prefer the tex image because, even if we have a renderbuffer, we may
247 * have had to wrap it in a texture view.
249 _mesa_meta_framebuffer_texture_image(ctx
, ctx
->ReadBuffer
, attachment
,
250 src_view_tex_image
, src_z
);
252 _mesa_framebuffer_renderbuffer(ctx
, ctx
->ReadBuffer
, attachment
,
256 status
= _mesa_check_framebuffer_status(ctx
, ctx
->ReadBuffer
);
257 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
260 if (dst_renderbuffer
) {
261 _mesa_framebuffer_renderbuffer(ctx
, ctx
->DrawBuffer
, attachment
,
264 _mesa_meta_framebuffer_texture_image(ctx
, ctx
->DrawBuffer
, attachment
,
265 dst_tex_image
, dst_z
);
268 status
= _mesa_check_framebuffer_status(ctx
, ctx
->DrawBuffer
);
269 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
272 /* Explicitly disable sRGB encoding */
273 ctx
->DrawBuffer
->Visual
.sRGBCapable
= false;
275 /* Since we've bound a new draw framebuffer, we need to update its
276 * derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to
279 _mesa_update_state(ctx
);
281 /* We skip the core BlitFramebuffer checks for format consistency.
282 * We have already created views to ensure that the texture formats
285 ctx
->Driver
.BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
287 src_x
+ src_width
, src_y
+ src_height
,
289 dst_x
+ src_width
, dst_y
+ src_height
,
295 _mesa_reference_framebuffer(&readFb
, NULL
);
296 _mesa_reference_framebuffer(&drawFb
, NULL
);
300 _mesa_DeleteTextures(1, &src_view_texture
);
302 /* If we got a renderbuffer source, delete the temporary texture */
303 if (src_renderbuffer
&& src_tex_image
)
304 ctx
->Driver
.DeleteTexture(ctx
, src_tex_image
->TexObject
);