1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Brian Paul 31 */ 32 33#include "main/imports.h" 34#include "main/image.h" 35#include "main/macros.h" 36 37#include "st_context.h" 38#include "st_texture.h" 39#include "st_cb_bitmap.h" 40#include "st_cb_blit.h" 41#include "st_cb_fbo.h" 42#include "st_manager.h" 43#include "st_scissor.h" 44#include "st_util.h" 45 46#include "util/u_format.h" 47 48static void 49st_BlitFramebuffer(struct gl_context *ctx, 50 struct gl_framebuffer *readFB, 51 struct gl_framebuffer *drawFB, 52 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 53 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 54 GLbitfield mask, GLenum filter) 55{ 56 const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT | 57 GL_STENCIL_BUFFER_BIT); 58 struct st_context *st = st_context(ctx); 59 const uint pFilter = ((filter == GL_NEAREST) 60 ? PIPE_TEX_FILTER_NEAREST 61 : PIPE_TEX_FILTER_LINEAR); 62 struct { 63 GLint srcX0, srcY0, srcX1, srcY1; 64 GLint dstX0, dstY0, dstX1, dstY1; 65 } clip; 66 struct pipe_blit_info blit; 67 68 st_manager_validate_framebuffers(st); 69 70 /* Make sure bitmap rendering has landed in the framebuffers */ 71 st_flush_bitmap_cache(st); 72 st_invalidate_readpix_cache(st); 73 74 clip.srcX0 = srcX0; 75 clip.srcY0 = srcY0; 76 clip.srcX1 = srcX1; 77 clip.srcY1 = srcY1; 78 clip.dstX0 = dstX0; 79 clip.dstY0 = dstY0; 80 clip.dstX1 = dstX1; 81 clip.dstY1 = dstY1; 82 83 /* NOTE: If the src and dst dimensions don't match, we cannot simply adjust 84 * the integer coordinates to account for clipping (or scissors) because that 85 * would make us cut off fractional parts, affecting the result of the blit. 86 * 87 * XXX: This should depend on mask ! 88 */ 89 if (!_mesa_clip_blit(ctx, readFB, drawFB, 90 &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1, 91 &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) { 92 return; /* nothing to draw/blit */ 93 } 94 memset(&blit, 0, sizeof(struct pipe_blit_info)); 95 blit.scissor_enable = 96 (dstX0 != clip.dstX0) || 97 (dstY0 != clip.dstY0) || 98 (dstX1 != clip.dstX1) || 99 (dstY1 != clip.dstY1); 100 101 if (st_fb_orientation(drawFB) == Y_0_TOP) { 102 /* invert Y for dest */ 103 dstY0 = drawFB->Height - dstY0; 104 dstY1 = drawFB->Height - dstY1; 105 /* invert Y for clip */ 106 clip.dstY0 = drawFB->Height - clip.dstY0; 107 clip.dstY1 = drawFB->Height - clip.dstY1; 108 } 109 if (blit.scissor_enable) { 110 blit.scissor.minx = MIN2(clip.dstX0, clip.dstX1); 111 blit.scissor.miny = MIN2(clip.dstY0, clip.dstY1); 112 blit.scissor.maxx = MAX2(clip.dstX0, clip.dstX1); 113 blit.scissor.maxy = MAX2(clip.dstY0, clip.dstY1); 114#if 0 115 debug_printf("scissor = (%i,%i)-(%i,%i)\n", 116 blit.scissor.minx,blit.scissor.miny, 117 blit.scissor.maxx,blit.scissor.maxy); 118#endif 119 } 120 121 if (st_fb_orientation(readFB) == Y_0_TOP) { 122 /* invert Y for src */ 123 srcY0 = readFB->Height - srcY0; 124 srcY1 = readFB->Height - srcY1; 125 } 126 127 if (srcY0 > srcY1 && dstY0 > dstY1) { 128 /* Both src and dst are upside down. Swap Y to make it 129 * right-side up to increase odds of using a fast path. 130 * Recall that all Gallium raster coords have Y=0=top. 131 */ 132 GLint tmp; 133 tmp = srcY0; 134 srcY0 = srcY1; 135 srcY1 = tmp; 136 tmp = dstY0; 137 dstY0 = dstY1; 138 dstY1 = tmp; 139 } 140 141 blit.src.box.depth = 1; 142 blit.dst.box.depth = 1; 143 144 /* Destination dimensions have to be positive: */ 145 if (dstX0 < dstX1) { 146 blit.dst.box.x = dstX0; 147 blit.src.box.x = srcX0; 148 blit.dst.box.width = dstX1 - dstX0; 149 blit.src.box.width = srcX1 - srcX0; 150 } else { 151 blit.dst.box.x = dstX1; 152 blit.src.box.x = srcX1; 153 blit.dst.box.width = dstX0 - dstX1; 154 blit.src.box.width = srcX0 - srcX1; 155 } 156 if (dstY0 < dstY1) { 157 blit.dst.box.y = dstY0; 158 blit.src.box.y = srcY0; 159 blit.dst.box.height = dstY1 - dstY0; 160 blit.src.box.height = srcY1 - srcY0; 161 } else { 162 blit.dst.box.y = dstY1; 163 blit.src.box.y = srcY1; 164 blit.dst.box.height = dstY0 - dstY1; 165 blit.src.box.height = srcY0 - srcY1; 166 } 167 168 if (drawFB != ctx->WinSysDrawBuffer) 169 st_window_rectangles_to_blit(ctx, &blit); 170 171 blit.filter = pFilter; 172 blit.render_condition_enable = TRUE; 173 blit.alpha_blend = FALSE; 174 175 if (mask & GL_COLOR_BUFFER_BIT) { 176 struct gl_renderbuffer_attachment *srcAtt = 177 &readFB->Attachment[readFB->_ColorReadBufferIndex]; 178 GLuint i; 179 180 blit.mask = PIPE_MASK_RGBA; 181 182 if (srcAtt->Type == GL_TEXTURE) { 183 struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture); 184 185 if (!srcObj || !srcObj->pt) { 186 return; 187 } 188 189 blit.src.resource = srcObj->pt; 190 blit.src.level = srcAtt->TextureLevel; 191 blit.src.box.z = srcAtt->Zoffset + srcAtt->CubeMapFace; 192 blit.src.format = srcObj->pt->format; 193 194 if (!ctx->Color.sRGBEnabled) 195 blit.src.format = util_format_linear(blit.src.format); 196 } 197 else { 198 struct st_renderbuffer *srcRb = 199 st_renderbuffer(readFB->_ColorReadBuffer); 200 struct pipe_surface *srcSurf; 201 202 if (!srcRb) 203 return; 204 205 st_update_renderbuffer_surface(st, srcRb); 206 207 if (!srcRb->surface) 208 return; 209 210 srcSurf = srcRb->surface; 211 212 blit.src.resource = srcSurf->texture; 213 blit.src.level = srcSurf->u.tex.level; 214 blit.src.box.z = srcSurf->u.tex.first_layer; 215 blit.src.format = srcSurf->format; 216 } 217 218 for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) { 219 struct st_renderbuffer *dstRb = 220 st_renderbuffer(drawFB->_ColorDrawBuffers[i]); 221 222 if (dstRb) { 223 struct pipe_surface *dstSurf; 224 225 st_update_renderbuffer_surface(st, dstRb); 226 227 dstSurf = dstRb->surface; 228 229 if (dstSurf) { 230 blit.dst.resource = dstSurf->texture; 231 blit.dst.level = dstSurf->u.tex.level; 232 blit.dst.box.z = dstSurf->u.tex.first_layer; 233 blit.dst.format = dstSurf->format; 234 235 st->pipe->blit(st->pipe, &blit); 236 dstRb->defined = true; /* front buffer tracking */ 237 } 238 } 239 } 240 } 241 242 if (mask & depthStencil) { 243 /* depth and/or stencil blit */ 244 245 /* get src/dst depth surfaces */ 246 struct st_renderbuffer *srcDepthRb = 247 st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer); 248 struct st_renderbuffer *dstDepthRb = 249 st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer); 250 struct pipe_surface *dstDepthSurf = 251 dstDepthRb ? dstDepthRb->surface : NULL; 252 253 struct st_renderbuffer *srcStencilRb = 254 st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer); 255 struct st_renderbuffer *dstStencilRb = 256 st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer); 257 struct pipe_surface *dstStencilSurf = 258 dstStencilRb ? dstStencilRb->surface : NULL; 259 260 if (_mesa_has_depthstencil_combined(readFB) && 261 _mesa_has_depthstencil_combined(drawFB)) { 262 blit.mask = 0; 263 if (mask & GL_DEPTH_BUFFER_BIT) 264 blit.mask |= PIPE_MASK_Z; 265 if (mask & GL_STENCIL_BUFFER_BIT) 266 blit.mask |= PIPE_MASK_S; 267 268 blit.dst.resource = dstDepthSurf->texture; 269 blit.dst.level = dstDepthSurf->u.tex.level; 270 blit.dst.box.z = dstDepthSurf->u.tex.first_layer; 271 blit.dst.format = dstDepthSurf->format; 272 273 blit.src.resource = srcDepthRb->texture; 274 blit.src.level = srcDepthRb->surface->u.tex.level; 275 blit.src.box.z = srcDepthRb->surface->u.tex.first_layer; 276 blit.src.format = srcDepthRb->surface->format; 277 278 st->pipe->blit(st->pipe, &blit); 279 } 280 else { 281 /* blitting depth and stencil separately */ 282 283 if (mask & GL_DEPTH_BUFFER_BIT) { 284 blit.mask = PIPE_MASK_Z; 285 286 blit.dst.resource = dstDepthSurf->texture; 287 blit.dst.level = dstDepthSurf->u.tex.level; 288 blit.dst.box.z = dstDepthSurf->u.tex.first_layer; 289 blit.dst.format = dstDepthSurf->format; 290 291 blit.src.resource = srcDepthRb->texture; 292 blit.src.level = srcDepthRb->surface->u.tex.level; 293 blit.src.box.z = srcDepthRb->surface->u.tex.first_layer; 294 blit.src.format = srcDepthRb->surface->format; 295 296 st->pipe->blit(st->pipe, &blit); 297 } 298 299 if (mask & GL_STENCIL_BUFFER_BIT) { 300 blit.mask = PIPE_MASK_S; 301 302 blit.dst.resource = dstStencilSurf->texture; 303 blit.dst.level = dstStencilSurf->u.tex.level; 304 blit.dst.box.z = dstStencilSurf->u.tex.first_layer; 305 blit.dst.format = dstStencilSurf->format; 306 307 blit.src.resource = srcStencilRb->texture; 308 blit.src.level = srcStencilRb->surface->u.tex.level; 309 blit.src.box.z = srcStencilRb->surface->u.tex.first_layer; 310 blit.src.format = srcStencilRb->surface->format; 311 312 st->pipe->blit(st->pipe, &blit); 313 } 314 } 315 } 316} 317 318 319void 320st_init_blit_functions(struct dd_function_table *functions) 321{ 322 functions->BlitFramebuffer = st_BlitFramebuffer; 323} 324