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.
39 * Create a texture image that wraps a renderbuffer.
41 static struct gl_texture_image
*
42 wrap_renderbuffer(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
)
45 struct gl_texture_object
*texObj
;
46 struct gl_texture_image
*texImage
;
48 if (rb
->NumSamples
> 1)
49 texTarget
= GL_TEXTURE_2D_MULTISAMPLE
;
51 texTarget
= GL_TEXTURE_2D
;
53 /* Texture ID is not significant since it never goes into the hash table */
54 texObj
= ctx
->Driver
.NewTextureObject(ctx
, 0, texTarget
);
59 texImage
= _mesa_get_tex_image(ctx
, texObj
, texTarget
, 0);
64 if (!ctx
->Driver
.BindRenderbufferTexImage(ctx
, rb
, texImage
)) {
65 _mesa_problem(ctx
, "Failed to create texture from renderbuffer");
69 if (ctx
->Driver
.FinishRenderTexture
&& !rb
->NeedsFinishRenderTexture
) {
70 rb
->NeedsFinishRenderTexture
= true;
71 ctx
->Driver
.FinishRenderTexture(ctx
, rb
);
78 /* This function makes a texture view without bothering with all of the API
79 * checks. Most of them are the same for CopyTexSubImage so checking would
80 * be redundant. The one major difference is that we don't check for
81 * whether the texture is immutable or not. However, since the view will
82 * be created and then immediately destroyed, this should not be a problem.
85 make_view(struct gl_context
*ctx
, struct gl_texture_image
*tex_image
,
86 struct gl_texture_image
**view_tex_image
, GLuint
*view_tex_name
,
87 GLenum internal_format
)
89 struct gl_texture_object
*tex_obj
= tex_image
->TexObject
;
90 struct gl_texture_object
*view_tex_obj
;
91 mesa_format tex_format
;
93 /* Set up the new texture object */
94 _mesa_GenTextures(1, view_tex_name
);
95 view_tex_obj
= _mesa_lookup_texture(ctx
, *view_tex_name
);
99 tex_format
= _mesa_choose_texture_format(ctx
, view_tex_obj
, tex_obj
->Target
,
103 if (!ctx
->Driver
.TestProxyTexImage(ctx
, tex_obj
->Target
, 0, tex_format
,
104 tex_image
->Width
, tex_image
->Height
,
105 tex_image
->Depth
, 0)) {
106 _mesa_DeleteTextures(1, view_tex_name
);
111 assert(tex_obj
->Target
!= 0);
112 assert(tex_obj
->TargetIndex
< NUM_TEXTURE_TARGETS
);
114 view_tex_obj
->Target
= tex_obj
->Target
;
115 view_tex_obj
->TargetIndex
= tex_obj
->TargetIndex
;
117 *view_tex_image
= _mesa_get_tex_image(ctx
, view_tex_obj
, tex_obj
->Target
, 0);
119 if (!*view_tex_image
) {
120 _mesa_DeleteTextures(1, view_tex_name
);
125 _mesa_init_teximage_fields(ctx
, *view_tex_image
,
126 tex_image
->Width
, tex_image
->Height
,
128 0, internal_format
, tex_format
);
130 view_tex_obj
->MinLevel
= tex_image
->Level
;
131 view_tex_obj
->NumLevels
= 1;
132 view_tex_obj
->MinLayer
= tex_obj
->MinLayer
;
133 view_tex_obj
->NumLayers
= tex_obj
->NumLayers
;
134 view_tex_obj
->Immutable
= tex_obj
->Immutable
;
135 view_tex_obj
->ImmutableLevels
= tex_obj
->ImmutableLevels
;
137 if (ctx
->Driver
.TextureView
!= NULL
&&
138 !ctx
->Driver
.TextureView(ctx
, view_tex_obj
, tex_obj
)) {
139 _mesa_DeleteTextures(1, view_tex_name
);
141 return false; /* driver recorded error */
147 /** A partial implementation of glCopyImageSubData
149 * This is a partial implementation of glCopyImageSubData that works only
150 * if both textures are uncompressed and the destination texture is
151 * renderable. It uses a slight abuse of a texture view (see make_view) to
152 * turn the source texture into the destination texture type and then uses
153 * _mesa_meta_BlitFramebuffers to do the copy.
156 _mesa_meta_CopyImageSubData_uncompressed(struct gl_context
*ctx
,
157 struct gl_texture_image
*src_tex_image
,
158 struct gl_renderbuffer
*src_renderbuffer
,
159 int src_x
, int src_y
, int src_z
,
160 struct gl_texture_image
*dst_tex_image
,
161 struct gl_renderbuffer
*dst_renderbuffer
,
162 int dst_x
, int dst_y
, int dst_z
,
163 int src_width
, int src_height
)
165 mesa_format src_format
, dst_format
;
166 GLint src_internal_format
, dst_internal_format
;
167 GLuint src_view_texture
= 0;
168 struct gl_texture_image
*src_view_tex_image
;
170 bool success
= false;
172 GLenum status
, attachment
;
174 if (src_renderbuffer
) {
175 src_format
= src_renderbuffer
->Format
;
176 src_internal_format
= src_renderbuffer
->InternalFormat
;
178 assert(src_tex_image
);
179 src_format
= src_tex_image
->TexFormat
;
180 src_internal_format
= src_tex_image
->InternalFormat
;
183 if (dst_renderbuffer
) {
184 dst_format
= dst_renderbuffer
->Format
;
185 dst_internal_format
= dst_renderbuffer
->InternalFormat
;
187 assert(dst_tex_image
);
188 dst_format
= dst_tex_image
->TexFormat
;
189 dst_internal_format
= dst_tex_image
->InternalFormat
;
192 if (_mesa_is_format_compressed(src_format
))
195 if (_mesa_is_format_compressed(dst_format
))
198 if (src_internal_format
== dst_internal_format
) {
199 src_view_tex_image
= src_tex_image
;
201 if (src_renderbuffer
) {
202 assert(src_tex_image
== NULL
);
203 src_tex_image
= wrap_renderbuffer(ctx
, src_renderbuffer
);
205 if (!make_view(ctx
, src_tex_image
, &src_view_tex_image
, &src_view_texture
,
206 dst_internal_format
))
210 /* We really only need to stash the bound framebuffers and scissor. */
211 _mesa_meta_begin(ctx
, MESA_META_SCISSOR
);
213 _mesa_GenFramebuffers(2, fbos
);
214 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
215 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
217 switch (_mesa_get_format_base_format(src_format
)) {
218 case GL_DEPTH_COMPONENT
:
219 attachment
= GL_DEPTH_ATTACHMENT
;
220 mask
= GL_DEPTH_BUFFER_BIT
;
222 case GL_DEPTH_STENCIL
:
223 attachment
= GL_DEPTH_STENCIL_ATTACHMENT
;
224 mask
= GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
;
226 case GL_STENCIL_INDEX
:
227 attachment
= GL_STENCIL_ATTACHMENT
;
228 mask
= GL_STENCIL_BUFFER_BIT
;
231 attachment
= GL_COLOR_ATTACHMENT0
;
232 mask
= GL_COLOR_BUFFER_BIT
;
233 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0
);
234 _mesa_ReadBuffer(GL_COLOR_ATTACHMENT0
);
237 if (src_view_tex_image
) {
238 /* Prefer the tex image because, even if we have a renderbuffer, we may
239 * have had to wrap it in a texture view.
241 _mesa_meta_framebuffer_texture_image(ctx
, ctx
->ReadBuffer
, attachment
,
242 src_view_tex_image
, src_z
);
244 _mesa_framebuffer_renderbuffer(ctx
, ctx
->ReadBuffer
, attachment
,
248 status
= _mesa_check_framebuffer_status(ctx
, ctx
->ReadBuffer
);
249 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
252 if (dst_renderbuffer
) {
253 _mesa_framebuffer_renderbuffer(ctx
, ctx
->DrawBuffer
, attachment
,
256 _mesa_meta_framebuffer_texture_image(ctx
, ctx
->DrawBuffer
, attachment
,
257 dst_tex_image
, dst_z
);
260 status
= _mesa_check_framebuffer_status(ctx
, ctx
->DrawBuffer
);
261 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
264 /* Since we've bound a new draw framebuffer, we need to update its
265 * derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to
268 _mesa_update_state(ctx
);
270 /* We skip the core BlitFramebuffer checks for format consistency.
271 * We have already created views to ensure that the texture formats
274 ctx
->Driver
.BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
276 src_x
+ src_width
, src_y
+ src_height
,
278 dst_x
+ src_width
, dst_y
+ src_height
,
284 _mesa_DeleteFramebuffers(2, fbos
);
288 _mesa_DeleteTextures(1, &src_view_texture
);
290 /* If we got a renderbuffer source, delete the temporary texture */
291 if (src_renderbuffer
&& src_tex_image
)
292 ctx
->Driver
.DeleteTexture(ctx
, src_tex_image
->TexObject
);