2 * Mesa 3-D graphics library
4 * Copyright (C) 2009 VMware, Inc. 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.
25 #include "main/glheader.h"
26 #include "main/mtypes.h"
27 #include "main/imports.h"
28 #include "main/arbprogram.h"
29 #include "main/arrayobj.h"
30 #include "main/blend.h"
31 #include "main/condrender.h"
32 #include "main/depth.h"
33 #include "main/enable.h"
34 #include "main/fbobject.h"
35 #include "main/macros.h"
36 #include "main/matrix.h"
37 #include "main/readpix.h"
38 #include "main/shaderapi.h"
39 #include "main/texobj.h"
40 #include "main/texenv.h"
41 #include "main/teximage.h"
42 #include "main/texparam.h"
43 #include "main/varray.h"
44 #include "main/viewport.h"
45 #include "swrast/swrast.h"
46 #include "drivers/common/meta.h"
47 #include "../glsl/ralloc.h"
49 /** Return offset in bytes of the field within a vertex struct */
50 #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
53 * One-time init for drawing depth pixels.
56 init_blit_depth_pixels(struct gl_context
*ctx
)
58 static const char *program
=
60 "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
63 struct blit_state
*blit
= &ctx
->Meta
->Blit
;
64 struct temp_texture
*tex
= _mesa_meta_get_temp_texture(ctx
);
65 const char *texTarget
;
67 assert(blit
->DepthFP
== 0);
69 /* replace %s with "RECT" or "2D" */
70 assert(strlen(program
) + 4 < sizeof(program2
));
71 if (tex
->Target
== GL_TEXTURE_RECTANGLE
)
75 _mesa_snprintf(program2
, sizeof(program2
), program
, texTarget
);
77 _mesa_GenProgramsARB(1, &blit
->DepthFP
);
78 _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, blit
->DepthFP
);
79 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
,
80 strlen(program2
), (const GLubyte
*) program2
);
84 setup_glsl_blit_framebuffer(struct gl_context
*ctx
,
85 struct blit_state
*blit
,
88 /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */
89 assert(_mesa_is_desktop_gl(ctx
) || target
== GL_TEXTURE_2D
);
91 _mesa_meta_setup_vertex_objects(&blit
->VAO
, &blit
->VBO
, true, 2, 2, 0);
93 _mesa_meta_setup_blit_shader(ctx
, target
, &blit
->shaders
);
97 * Try to do a color-only glBlitFramebuffer using texturing.
99 * We can do this when the src renderbuffer is actually a texture, or when the
100 * driver exposes BindRenderbufferTexImage().
103 blitframebuffer_texture(struct gl_context
*ctx
,
104 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
105 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
106 GLenum filter
, GLint flipX
, GLint flipY
,
107 GLboolean glsl_version
)
109 const struct gl_framebuffer
*readFb
= ctx
->ReadBuffer
;
110 const struct gl_renderbuffer_attachment
*readAtt
=
111 &readFb
->Attachment
[readFb
->_ColorReadBufferIndex
];
112 struct blit_state
*blit
= &ctx
->Meta
->Blit
;
113 const GLint dstX
= MIN2(dstX0
, dstX1
);
114 const GLint dstY
= MIN2(dstY0
, dstY1
);
115 const GLint dstW
= abs(dstX1
- dstX0
);
116 const GLint dstH
= abs(dstY1
- dstY0
);
117 struct gl_texture_object
*texObj
;
122 GLuint sampler
, samplerSave
=
123 ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].Sampler
?
124 ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].Sampler
->Name
: 0;
127 if (readAtt
->Texture
) {
128 /* If there's a texture attached of a type we can handle, then just use
131 srcLevel
= readAtt
->TextureLevel
;
132 texObj
= readAtt
->Texture
;
133 target
= texObj
->Target
;
135 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE_ARB
)
137 } else if (ctx
->Driver
.BindRenderbufferTexImage
) {
138 /* Otherwise, we need the driver to be able to bind a renderbuffer as
141 struct gl_texture_image
*texImage
;
142 struct gl_renderbuffer
*rb
= readAtt
->Renderbuffer
;
144 target
= GL_TEXTURE_2D
;
145 _mesa_GenTextures(1, &tempTex
);
146 _mesa_BindTexture(target
, tempTex
);
148 texObj
= _mesa_lookup_texture(ctx
, tempTex
);
149 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, srcLevel
);
151 if (!ctx
->Driver
.BindRenderbufferTexImage(ctx
, rb
, texImage
)) {
152 _mesa_DeleteTextures(1, &tempTex
);
155 if (ctx
->Driver
.FinishRenderTexture
&&
156 !rb
->NeedsFinishRenderTexture
) {
157 rb
->NeedsFinishRenderTexture
= true;
158 ctx
->Driver
.FinishRenderTexture(ctx
, rb
);
161 if (_mesa_is_winsys_fbo(readFb
)) {
163 srcY0
= rb
->Height
- srcY1
;
164 srcY1
= rb
->Height
- temp
;
172 baseLevelSave
= texObj
->BaseLevel
;
173 maxLevelSave
= texObj
->MaxLevel
;
176 setup_glsl_blit_framebuffer(ctx
, blit
, target
);
179 _mesa_meta_setup_ff_tnl_for_blit(&ctx
->Meta
->Blit
.VAO
,
180 &ctx
->Meta
->Blit
.VBO
,
184 _mesa_GenSamplers(1, &sampler
);
185 _mesa_BindSampler(ctx
->Texture
.CurrentUnit
, sampler
);
188 printf("Blit from texture!\n");
189 printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
190 printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
193 /* Prepare src texture state */
194 _mesa_BindTexture(target
, texObj
->Name
);
195 _mesa_SamplerParameteri(sampler
, GL_TEXTURE_MIN_FILTER
, filter
);
196 _mesa_SamplerParameteri(sampler
, GL_TEXTURE_MAG_FILTER
, filter
);
197 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
198 _mesa_TexParameteri(target
, GL_TEXTURE_BASE_LEVEL
, srcLevel
);
199 _mesa_TexParameteri(target
, GL_TEXTURE_MAX_LEVEL
, srcLevel
);
201 _mesa_SamplerParameteri(sampler
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
202 _mesa_SamplerParameteri(sampler
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
204 /* Always do our blits with no sRGB decode or encode. Note that
205 * GL_FRAMEBUFFER_SRGB has already been disabled by
206 * _mesa_meta_begin().
208 if (ctx
->Extensions
.EXT_texture_sRGB_decode
) {
209 _mesa_SamplerParameteri(sampler
, GL_TEXTURE_SRGB_DECODE_EXT
,
213 if (ctx
->API
== API_OPENGL_COMPAT
|| ctx
->API
== API_OPENGLES
) {
214 _mesa_TexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
215 _mesa_set_enable(ctx
, target
, GL_TRUE
);
218 /* Prepare vertex data (the VBO was previously created and bound) */
220 struct vertex verts
[4];
221 GLfloat s0
, t0
, s1
, t1
;
223 if (target
== GL_TEXTURE_2D
) {
224 const struct gl_texture_image
*texImage
225 = _mesa_select_tex_image(ctx
, texObj
, target
, srcLevel
);
226 s0
= srcX0
/ (float) texImage
->Width
;
227 s1
= srcX1
/ (float) texImage
->Width
;
228 t0
= srcY0
/ (float) texImage
->Height
;
229 t1
= srcY1
/ (float) texImage
->Height
;
232 assert(target
== GL_TEXTURE_RECTANGLE_ARB
);
239 /* Silence valgrind warnings about reading uninitialized stack. */
240 memset(verts
, 0, sizeof(verts
));
242 /* setup vertex positions */
243 verts
[0].x
= -1.0F
* flipX
;
244 verts
[0].y
= -1.0F
* flipY
;
245 verts
[1].x
= 1.0F
* flipX
;
246 verts
[1].y
= -1.0F
* flipY
;
247 verts
[2].x
= 1.0F
* flipX
;
248 verts
[2].y
= 1.0F
* flipY
;
249 verts
[3].x
= -1.0F
* flipX
;
250 verts
[3].y
= 1.0F
* flipY
;
252 verts
[0].tex
[0] = s0
;
253 verts
[0].tex
[1] = t0
;
254 verts
[1].tex
[0] = s1
;
255 verts
[1].tex
[1] = t0
;
256 verts
[2].tex
[0] = s1
;
257 verts
[2].tex
[1] = t1
;
258 verts
[3].tex
[0] = s0
;
259 verts
[3].tex
[1] = t1
;
261 _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB
, 0, sizeof(verts
), verts
);
265 _mesa_set_viewport(ctx
, 0, dstX
, dstY
, dstW
, dstH
);
266 _mesa_ColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
267 _mesa_DepthMask(GL_FALSE
);
268 _mesa_DrawArrays(GL_TRIANGLE_FAN
, 0, 4);
270 /* Restore texture object state, the texture binding will
271 * be restored by _mesa_meta_end().
273 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
274 _mesa_TexParameteri(target
, GL_TEXTURE_BASE_LEVEL
, baseLevelSave
);
275 _mesa_TexParameteri(target
, GL_TEXTURE_MAX_LEVEL
, maxLevelSave
);
278 _mesa_BindSampler(ctx
->Texture
.CurrentUnit
, samplerSave
);
279 _mesa_DeleteSamplers(1, &sampler
);
281 _mesa_DeleteTextures(1, &tempTex
);
287 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
288 * of texture mapping and polygon rendering.
291 _mesa_meta_BlitFramebuffer(struct gl_context
*ctx
,
292 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
293 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
294 GLbitfield mask
, GLenum filter
)
296 struct blit_state
*blit
= &ctx
->Meta
->Blit
;
297 struct temp_texture
*tex
= _mesa_meta_get_temp_texture(ctx
);
298 struct temp_texture
*depthTex
= _mesa_meta_get_temp_depth_texture(ctx
);
299 const GLsizei maxTexSize
= tex
->MaxSize
;
300 const GLint srcX
= MIN2(srcX0
, srcX1
);
301 const GLint srcY
= MIN2(srcY0
, srcY1
);
302 const GLint srcW
= abs(srcX1
- srcX0
);
303 const GLint srcH
= abs(srcY1
- srcY0
);
304 const GLint dstX
= MIN2(dstX0
, dstX1
);
305 const GLint dstY
= MIN2(dstY0
, dstY1
);
306 const GLint dstW
= abs(dstX1
- dstX0
);
307 const GLint dstH
= abs(dstY1
- dstY0
);
308 const GLint srcFlipX
= (srcX1
- srcX0
) / srcW
;
309 const GLint srcFlipY
= (srcY1
- srcY0
) / srcH
;
310 const GLint dstFlipX
= (dstX1
- dstX0
) / dstW
;
311 const GLint dstFlipY
= (dstY1
- dstY0
) / dstH
;
312 const GLint flipX
= srcFlipX
* dstFlipX
;
313 const GLint flipY
= srcFlipY
* dstFlipY
;
315 struct vertex verts
[4];
317 const GLboolean use_glsl_version
= ctx
->Extensions
.ARB_vertex_shader
&&
318 ctx
->Extensions
.ARB_fragment_shader
&&
319 (ctx
->API
!= API_OPENGLES
);
321 /* In addition to falling back if the blit size is larger than the maximum
322 * texture size, fallback if the source is multisampled. This fallback can
323 * be removed once Mesa gets support ARB_texture_multisample.
325 if (srcW
> maxTexSize
|| srcH
> maxTexSize
326 || ctx
->ReadBuffer
->Visual
.samples
> 0) {
327 /* XXX avoid this fallback */
328 _swrast_BlitFramebuffer(ctx
, srcX0
, srcY0
, srcX1
, srcY1
,
329 dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
333 /* only scissor effects blit so save/clear all other relevant state */
334 _mesa_meta_begin(ctx
, ~MESA_META_SCISSOR
);
336 /* Try faster, direct texture approach first */
337 if (mask
& GL_COLOR_BUFFER_BIT
) {
338 if (blitframebuffer_texture(ctx
, srcX0
, srcY0
, srcX1
, srcY1
,
339 dstX0
, dstY0
, dstX1
, dstY1
,
340 filter
, dstFlipX
, dstFlipY
,
342 mask
&= ~GL_COLOR_BUFFER_BIT
;
350 /* Choose between glsl version and fixed function version of
351 * BlitFramebuffer function.
353 if (use_glsl_version
) {
354 setup_glsl_blit_framebuffer(ctx
, blit
, tex
->Target
);
357 _mesa_meta_setup_ff_tnl_for_blit(&blit
->VAO
, &blit
->VBO
, 2);
360 /* Silence valgrind warnings about reading uninitialized stack. */
361 memset(verts
, 0, sizeof(verts
));
363 /* Continue with "normal" approach which involves copying the src rect
364 * into a temporary texture and is "blitted" by drawing a textured quad.
367 /* setup vertex positions */
368 verts
[0].x
= -1.0F
* flipX
;
369 verts
[0].y
= -1.0F
* flipY
;
370 verts
[1].x
= 1.0F
* flipX
;
371 verts
[1].y
= -1.0F
* flipY
;
372 verts
[2].x
= 1.0F
* flipX
;
373 verts
[2].y
= 1.0F
* flipY
;
374 verts
[3].x
= -1.0F
* flipX
;
375 verts
[3].y
= 1.0F
* flipY
;
379 /* glEnable() in gles2 and gles3 doesn't allow GL_TEXTURE_{1D, 2D, etc.}
382 if (_mesa_is_desktop_gl(ctx
) || ctx
->API
== API_OPENGLES
)
383 _mesa_set_enable(ctx
, tex
->Target
, GL_TRUE
);
385 if (mask
& GL_COLOR_BUFFER_BIT
) {
386 const struct gl_framebuffer
*readFb
= ctx
->ReadBuffer
;
387 const struct gl_renderbuffer
*colorReadRb
= readFb
->_ColorReadBuffer
;
388 const GLenum rb_base_format
=
389 _mesa_base_tex_format(ctx
, colorReadRb
->InternalFormat
);
391 /* Using the exact source rectangle to create the texture does incorrect
392 * linear filtering along the edges. So, allocate the texture extended along
393 * edges by one pixel in x, y directions.
395 _mesa_meta_setup_copypix_texture(ctx
, tex
,
396 srcX
- 1, srcY
- 1, srcW
+ 2, srcH
+ 2,
397 rb_base_format
, filter
);
398 /* texcoords (after texture allocation!) */
400 verts
[0].tex
[0] = 1.0F
;
401 verts
[0].tex
[1] = 1.0F
;
402 verts
[1].tex
[0] = tex
->Sright
- 1.0F
;
403 verts
[1].tex
[1] = 1.0F
;
404 verts
[2].tex
[0] = tex
->Sright
- 1.0F
;
405 verts
[2].tex
[1] = tex
->Ttop
- 1.0F
;
406 verts
[3].tex
[0] = 1.0F
;
407 verts
[3].tex
[1] = tex
->Ttop
- 1.0F
;
409 /* upload new vertex data */
410 _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB
, 0, sizeof(verts
), verts
);
413 _mesa_set_viewport(ctx
, 0, dstX
, dstY
, dstW
, dstH
);
414 _mesa_ColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
415 _mesa_set_enable(ctx
, GL_DEPTH_TEST
, GL_FALSE
);
416 _mesa_DepthMask(GL_FALSE
);
417 _mesa_DrawArrays(GL_TRIANGLE_FAN
, 0, 4);
418 mask
&= ~GL_COLOR_BUFFER_BIT
;
421 if ((mask
& GL_DEPTH_BUFFER_BIT
) &&
422 _mesa_is_desktop_gl(ctx
) &&
423 ctx
->Extensions
.ARB_depth_texture
&&
424 ctx
->Extensions
.ARB_fragment_program
) {
426 GLuint
*tmp
= malloc(srcW
* srcH
* sizeof(GLuint
));
430 newTex
= _mesa_meta_alloc_texture(depthTex
, srcW
, srcH
,
432 _mesa_ReadPixels(srcX
, srcY
, srcW
, srcH
, GL_DEPTH_COMPONENT
,
433 GL_UNSIGNED_INT
, tmp
);
434 _mesa_meta_setup_drawpix_texture(ctx
, depthTex
, newTex
,
435 srcW
, srcH
, GL_DEPTH_COMPONENT
,
436 GL_UNSIGNED_INT
, tmp
);
438 /* texcoords (after texture allocation!) */
440 verts
[0].tex
[0] = 0.0F
;
441 verts
[0].tex
[1] = 0.0F
;
442 verts
[1].tex
[0] = depthTex
->Sright
;
443 verts
[1].tex
[1] = 0.0F
;
444 verts
[2].tex
[0] = depthTex
->Sright
;
445 verts
[2].tex
[1] = depthTex
->Ttop
;
446 verts
[3].tex
[0] = 0.0F
;
447 verts
[3].tex
[1] = depthTex
->Ttop
;
449 /* upload new vertex data */
450 _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB
, 0, sizeof(verts
), verts
);
454 init_blit_depth_pixels(ctx
);
456 _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, blit
->DepthFP
);
457 _mesa_set_enable(ctx
, GL_FRAGMENT_PROGRAM_ARB
, GL_TRUE
);
458 _mesa_ColorMask(GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
459 _mesa_set_enable(ctx
, GL_DEPTH_TEST
, GL_TRUE
);
460 _mesa_DepthFunc(GL_ALWAYS
);
461 _mesa_DepthMask(GL_TRUE
);
463 _mesa_set_viewport(ctx
, 0, dstX
, dstY
, dstW
, dstH
);
464 _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB
, 0, sizeof(verts
), verts
);
465 _mesa_DrawArrays(GL_TRIANGLE_FAN
, 0, 4);
466 mask
&= ~GL_DEPTH_BUFFER_BIT
;
472 if (mask
& GL_STENCIL_BUFFER_BIT
) {
473 /* XXX can't easily do stencil */
476 if (_mesa_is_desktop_gl(ctx
) || ctx
->API
== API_OPENGLES
)
477 _mesa_set_enable(ctx
, tex
->Target
, GL_FALSE
);
482 _swrast_BlitFramebuffer(ctx
, srcX0
, srcY0
, srcX1
, srcY1
,
483 dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
488 _mesa_meta_glsl_blit_cleanup(struct blit_state
*blit
)
491 _mesa_DeleteVertexArrays(1, &blit
->VAO
);
493 _mesa_DeleteBuffers(1, &blit
->VBO
);
497 _mesa_DeleteProgramsARB(1, &blit
->DepthFP
);
501 _mesa_meta_blit_shader_table_cleanup(&blit
->shaders
);
503 _mesa_DeleteTextures(1, &blit
->depthTex
.TexObj
);
504 blit
->depthTex
.TexObj
= 0;