1/* 2 * Copyright 2003 VMware, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26#include "main/image.h" 27#include "main/state.h" 28#include "main/stencil.h" 29#include "main/mtypes.h" 30#include "main/condrender.h" 31#include "main/fbobject.h" 32#include "drivers/common/meta.h" 33 34#include "brw_context.h" 35#include "intel_buffers.h" 36#include "intel_mipmap_tree.h" 37#include "intel_pixel.h" 38#include "intel_fbo.h" 39#include "intel_blit.h" 40#include "intel_batchbuffer.h" 41 42#define FILE_DEBUG_FLAG DEBUG_PIXEL 43 44/** 45 * CopyPixels with the blitter. Don't support zooming, pixel transfer, etc. 46 */ 47static bool 48do_blit_copypixels(struct gl_context * ctx, 49 GLint srcx, GLint srcy, 50 GLsizei width, GLsizei height, 51 GLint dstx, GLint dsty, GLenum type) 52{ 53 struct brw_context *brw = brw_context(ctx); 54 struct gl_framebuffer *fb = ctx->DrawBuffer; 55 struct gl_framebuffer *read_fb = ctx->ReadBuffer; 56 GLint orig_dstx; 57 GLint orig_dsty; 58 GLint orig_srcx; 59 GLint orig_srcy; 60 struct intel_renderbuffer *draw_irb = NULL; 61 struct intel_renderbuffer *read_irb = NULL; 62 63 /* Update draw buffer bounds */ 64 _mesa_update_state(ctx); 65 66 intel_prepare_render(brw); 67 68 switch (type) { 69 case GL_COLOR: 70 if (fb->_NumColorDrawBuffers != 1) { 71 perf_debug("glCopyPixels() fallback: MRT\n"); 72 return false; 73 } 74 75 draw_irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); 76 read_irb = intel_renderbuffer(read_fb->_ColorReadBuffer); 77 break; 78 case GL_DEPTH_STENCIL_EXT: 79 draw_irb = intel_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); 80 read_irb = 81 intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer); 82 break; 83 case GL_DEPTH: 84 perf_debug("glCopyPixels() fallback: GL_DEPTH\n"); 85 return false; 86 case GL_STENCIL: 87 perf_debug("glCopyPixels() fallback: GL_STENCIL\n"); 88 return false; 89 default: 90 perf_debug("glCopyPixels(): Unknown type\n"); 91 return false; 92 } 93 94 if (!draw_irb) { 95 perf_debug("glCopyPixels() fallback: missing draw buffer\n"); 96 return false; 97 } 98 99 if (!read_irb) { 100 perf_debug("glCopyPixels() fallback: missing read buffer\n"); 101 return false; 102 } 103 104 if (draw_irb->mt->surf.samples > 1 || read_irb->mt->surf.samples > 1) { 105 perf_debug("glCopyPixels() fallback: multisampled buffers\n"); 106 return false; 107 } 108 109 if (ctx->_ImageTransferState) { 110 perf_debug("glCopyPixels(): Unsupported image transfer state\n"); 111 return false; 112 } 113 114 if (ctx->Depth.Test) { 115 perf_debug("glCopyPixels(): Unsupported depth test state\n"); 116 return false; 117 } 118 119 if (brw->stencil_enabled) { 120 perf_debug("glCopyPixels(): Unsupported stencil test state\n"); 121 return false; 122 } 123 124 if (ctx->Fog.Enabled || 125 ctx->Texture._MaxEnabledTexImageUnit != -1 || 126 _mesa_arb_fragment_program_enabled(ctx)) { 127 perf_debug("glCopyPixels(): Unsupported fragment shader state\n"); 128 return false; 129 } 130 131 if (ctx->Color.AlphaEnabled || 132 ctx->Color.BlendEnabled) { 133 perf_debug("glCopyPixels(): Unsupported blend state\n"); 134 return false; 135 } 136 137 if (GET_COLORMASK(ctx->Color.ColorMask, 0) != 0xf) { 138 perf_debug("glCopyPixels(): Unsupported color mask state\n"); 139 return false; 140 } 141 142 if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) { 143 perf_debug("glCopyPixels(): Unsupported pixel zoom\n"); 144 return false; 145 } 146 147 intel_batchbuffer_flush(brw); 148 149 /* Clip to destination buffer. */ 150 orig_dstx = dstx; 151 orig_dsty = dsty; 152 if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, 153 fb->_Xmax, fb->_Ymax, 154 &dstx, &dsty, &width, &height)) 155 goto out; 156 /* Adjust src coords for our post-clipped destination origin */ 157 srcx += dstx - orig_dstx; 158 srcy += dsty - orig_dsty; 159 160 /* Clip to source buffer. */ 161 orig_srcx = srcx; 162 orig_srcy = srcy; 163 if (!_mesa_clip_to_region(0, 0, 164 read_fb->Width, read_fb->Height, 165 &srcx, &srcy, &width, &height)) 166 goto out; 167 /* Adjust dst coords for our post-clipped source origin */ 168 dstx += srcx - orig_srcx; 169 dsty += srcy - orig_srcy; 170 171 if (!intel_miptree_blit(brw, 172 read_irb->mt, read_irb->mt_level, read_irb->mt_layer, 173 srcx, srcy, read_fb->FlipY, 174 draw_irb->mt, draw_irb->mt_level, draw_irb->mt_layer, 175 dstx, dsty, fb->FlipY, 176 width, height, 177 (ctx->Color.ColorLogicOpEnabled ? 178 ctx->Color._LogicOp : COLOR_LOGICOP_COPY))) { 179 DBG("%s: blit failure\n", __func__); 180 return false; 181 } 182 183 if (ctx->Query.CurrentOcclusionObject) 184 ctx->Query.CurrentOcclusionObject->Result += width * height; 185 186out: 187 188 DBG("%s: success\n", __func__); 189 return true; 190} 191 192 193void 194intelCopyPixels(struct gl_context * ctx, 195 GLint srcx, GLint srcy, 196 GLsizei width, GLsizei height, 197 GLint destx, GLint desty, GLenum type) 198{ 199 struct brw_context *brw = brw_context(ctx); 200 201 DBG("%s\n", __func__); 202 203 if (!_mesa_check_conditional_render(ctx)) 204 return; 205 206 if (brw->screen->devinfo.gen < 6 && 207 do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) 208 return; 209 210 /* this will use swrast if needed */ 211 _mesa_meta_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type); 212} 213