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 view_tex_obj
->Target
= tex_obj
->Target
;
113 *view_tex_image
= _mesa_get_tex_image(ctx
, view_tex_obj
, tex_obj
->Target
, 0);
115 if (!*view_tex_image
) {
116 _mesa_DeleteTextures(1, view_tex_name
);
121 _mesa_init_teximage_fields(ctx
, *view_tex_image
,
122 tex_image
->Width
, tex_image
->Height
,
124 0, internal_format
, tex_format
);
126 view_tex_obj
->MinLevel
= tex_image
->Level
;
127 view_tex_obj
->NumLevels
= 1;
128 view_tex_obj
->MinLayer
= tex_obj
->MinLayer
;
129 view_tex_obj
->NumLayers
= tex_obj
->NumLayers
;
130 view_tex_obj
->Immutable
= tex_obj
->Immutable
;
131 view_tex_obj
->ImmutableLevels
= tex_obj
->ImmutableLevels
;
132 view_tex_obj
->Target
= tex_obj
->Target
;
134 if (ctx
->Driver
.TextureView
!= NULL
&&
135 !ctx
->Driver
.TextureView(ctx
, view_tex_obj
, tex_obj
)) {
136 _mesa_DeleteTextures(1, view_tex_name
);
138 return false; /* driver recorded error */
144 /** A partial implementation of glCopyImageSubData
146 * This is a partial implementation of glCopyImageSubData that works only
147 * if both textures are uncompressed and the destination texture is
148 * renderable. It uses a slight abuse of a texture view (see make_view) to
149 * turn the source texture into the destination texture type and then uses
150 * _mesa_meta_BlitFramebuffers to do the copy.
153 _mesa_meta_CopyImageSubData_uncompressed(struct gl_context
*ctx
,
154 struct gl_texture_image
*src_tex_image
,
155 struct gl_renderbuffer
*src_renderbuffer
,
156 int src_x
, int src_y
, int src_z
,
157 struct gl_texture_image
*dst_tex_image
,
158 struct gl_renderbuffer
*dst_renderbuffer
,
159 int dst_x
, int dst_y
, int dst_z
,
160 int src_width
, int src_height
)
162 mesa_format src_format
, dst_format
;
163 GLint src_internal_format
, dst_internal_format
;
164 GLuint src_view_texture
= 0;
165 struct gl_texture_image
*src_view_tex_image
;
167 bool success
= false;
169 GLenum status
, attachment
;
171 if (src_renderbuffer
) {
172 src_format
= src_renderbuffer
->Format
;
173 src_internal_format
= src_renderbuffer
->InternalFormat
;
175 assert(src_tex_image
);
176 src_format
= src_tex_image
->TexFormat
;
177 src_internal_format
= src_tex_image
->InternalFormat
;
180 if (dst_renderbuffer
) {
181 dst_format
= dst_renderbuffer
->Format
;
182 dst_internal_format
= dst_renderbuffer
->InternalFormat
;
184 assert(dst_tex_image
);
185 dst_format
= dst_tex_image
->TexFormat
;
186 dst_internal_format
= dst_tex_image
->InternalFormat
;
189 if (_mesa_is_format_compressed(src_format
))
192 if (_mesa_is_format_compressed(dst_format
))
195 if (src_internal_format
== dst_internal_format
) {
196 src_view_tex_image
= src_tex_image
;
198 if (src_renderbuffer
) {
199 assert(src_tex_image
== NULL
);
200 src_tex_image
= wrap_renderbuffer(ctx
, src_renderbuffer
);
202 if (!make_view(ctx
, src_tex_image
, &src_view_tex_image
, &src_view_texture
,
203 dst_tex_image
->InternalFormat
))
207 /* We really only need to stash the bound framebuffers and scissor. */
208 _mesa_meta_begin(ctx
, MESA_META_SCISSOR
);
210 _mesa_GenFramebuffers(2, fbos
);
211 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
212 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
214 switch (_mesa_get_format_base_format(src_format
)) {
215 case GL_DEPTH_COMPONENT
:
216 attachment
= GL_DEPTH_ATTACHMENT
;
217 mask
= GL_DEPTH_BUFFER_BIT
;
219 case GL_DEPTH_STENCIL
:
220 attachment
= GL_DEPTH_STENCIL_ATTACHMENT
;
221 mask
= GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
;
223 case GL_STENCIL_INDEX
:
224 attachment
= GL_STENCIL_ATTACHMENT
;
225 mask
= GL_STENCIL_BUFFER_BIT
;
228 attachment
= GL_COLOR_ATTACHMENT0
;
229 mask
= GL_COLOR_BUFFER_BIT
;
230 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0
);
231 _mesa_ReadBuffer(GL_COLOR_ATTACHMENT0
);
234 if (src_view_tex_image
) {
235 /* Prever the tex image because, even if we have a renderbuffer, we may
236 * have had to wrap it in a texture view.
238 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, attachment
,
239 src_view_tex_image
, src_z
);
241 _mesa_FramebufferRenderbuffer(GL_READ_FRAMEBUFFER
,
244 src_renderbuffer
->Name
);
247 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
248 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
251 if (dst_renderbuffer
) {
252 _mesa_FramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER
,
255 dst_renderbuffer
->Name
);
257 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, attachment
,
258 dst_tex_image
, dst_z
);
261 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
262 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
265 /* Since we've bound a new draw framebuffer, we need to update its
266 * derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to
269 _mesa_update_state(ctx
);
271 /* We skip the core BlitFramebuffer checks for format consistency.
272 * We have already created views to ensure that the texture formats
275 ctx
->Driver
.BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
277 src_x
+ src_width
, src_y
+ src_height
,
279 dst_x
+ src_width
, dst_y
+ src_height
,
285 _mesa_DeleteFramebuffers(2, fbos
);
289 _mesa_DeleteTextures(1, &src_view_texture
);
291 /* If we got a renderbuffer source, delete the temporary texture */
292 if (src_renderbuffer
&& src_tex_image
)
293 ctx
->Driver
.DeleteTexture(ctx
, src_tex_image
->TexObject
);