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/mtypes.h" 29#include "main/condrender.h" 30#include "main/fbobject.h" 31#include "drivers/common/meta.h" 32 33#include "brw_context.h" 34#include "intel_buffers.h" 35#include "intel_mipmap_tree.h" 36#include "intel_pixel.h" 37#include "intel_fbo.h" 38#include "intel_blit.h" 39#include "intel_batchbuffer.h" 40 41#define FILE_DEBUG_FLAG DEBUG_PIXEL 42 43/** 44 * CopyPixels with the blitter. Don't support zooming, pixel transfer, etc. 45 */ 46static bool 47do_blit_copypixels(struct gl_context * ctx, 48 GLint srcx, GLint srcy, 49 GLsizei width, GLsizei height, 50 GLint dstx, GLint dsty, GLenum type) 51{ 52 struct brw_context *brw = brw_context(ctx); 53 struct gl_framebuffer *fb = ctx->DrawBuffer; 54 struct gl_framebuffer *read_fb = ctx->ReadBuffer; 55 GLint orig_dstx; 56 GLint orig_dsty; 57 GLint orig_srcx; 58 GLint orig_srcy; 59 struct intel_renderbuffer *draw_irb = NULL; 60 struct intel_renderbuffer *read_irb = NULL; 61 62 /* Update draw buffer bounds */ 63 _mesa_update_state(ctx); 64 65 intel_prepare_render(brw); 66 67 switch (type) { 68 case GL_COLOR: 69 if (fb->_NumColorDrawBuffers != 1) { 70 perf_debug("glCopyPixels() fallback: MRT\n"); 71 return false; 72 } 73 74 draw_irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); 75 read_irb = intel_renderbuffer(read_fb->_ColorReadBuffer); 76 break; 77 case GL_DEPTH_STENCIL_EXT: 78 draw_irb = intel_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); 79 read_irb = 80 intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer); 81 break; 82 case GL_DEPTH: 83 perf_debug("glCopyPixels() fallback: GL_DEPTH\n"); 84 return false; 85 case GL_STENCIL: 86 perf_debug("glCopyPixels() fallback: GL_STENCIL\n"); 87 return false; 88 default: 89 perf_debug("glCopyPixels(): Unknown type\n"); 90 return false; 91 } 92 93 if (!draw_irb) { 94 perf_debug("glCopyPixels() fallback: missing draw buffer\n"); 95 return false; 96 } 97 98 if (!read_irb) { 99 perf_debug("glCopyPixels() fallback: missing read buffer\n"); 100 return false; 101 } 102 103 if (draw_irb->mt->num_samples > 1 || read_irb->mt->num_samples > 1) { 104 perf_debug("glCopyPixels() fallback: multisampled buffers\n"); 105 return false; 106 } 107 108 if (ctx->_ImageTransferState) { 109 perf_debug("glCopyPixels(): Unsupported image transfer state\n"); 110 return false; 111 } 112 113 if (ctx->Depth.Test) { 114 perf_debug("glCopyPixels(): Unsupported depth test state\n"); 115 return false; 116 } 117 118 if (ctx->Stencil._Enabled) { 119 perf_debug("glCopyPixels(): Unsupported stencil test state\n"); 120 return false; 121 } 122 123 if (ctx->Fog.Enabled || 124 ctx->Texture._MaxEnabledTexImageUnit != -1 || 125 ctx->FragmentProgram._Enabled) { 126 perf_debug("glCopyPixels(): Unsupported fragment shader state\n"); 127 return false; 128 } 129 130 if (ctx->Color.AlphaEnabled || 131 ctx->Color.BlendEnabled) { 132 perf_debug("glCopyPixels(): Unsupported blend state\n"); 133 return false; 134 } 135 136 if (!ctx->Color.ColorMask[0][0] || 137 !ctx->Color.ColorMask[0][1] || 138 !ctx->Color.ColorMask[0][2] || 139 !ctx->Color.ColorMask[0][3]) { 140 perf_debug("glCopyPixels(): Unsupported color mask state\n"); 141 return false; 142 } 143 144 if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) { 145 perf_debug("glCopyPixels(): Unsupported pixel zoom\n"); 146 return false; 147 } 148 149 intel_batchbuffer_flush(brw); 150 151 /* Clip to destination buffer. */ 152 orig_dstx = dstx; 153 orig_dsty = dsty; 154 if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, 155 fb->_Xmax, fb->_Ymax, 156 &dstx, &dsty, &width, &height)) 157 goto out; 158 /* Adjust src coords for our post-clipped destination origin */ 159 srcx += dstx - orig_dstx; 160 srcy += dsty - orig_dsty; 161 162 /* Clip to source buffer. */ 163 orig_srcx = srcx; 164 orig_srcy = srcy; 165 if (!_mesa_clip_to_region(0, 0, 166 read_fb->Width, read_fb->Height, 167 &srcx, &srcy, &width, &height)) 168 goto out; 169 /* Adjust dst coords for our post-clipped source origin */ 170 dstx += srcx - orig_srcx; 171 dsty += srcy - orig_srcy; 172 173 if (!intel_miptree_blit(brw, 174 read_irb->mt, read_irb->mt_level, read_irb->mt_layer, 175 srcx, srcy, _mesa_is_winsys_fbo(read_fb), 176 draw_irb->mt, draw_irb->mt_level, draw_irb->mt_layer, 177 dstx, dsty, _mesa_is_winsys_fbo(fb), 178 width, height, 179 (ctx->Color.ColorLogicOpEnabled ? 180 ctx->Color.LogicOp : GL_COPY))) { 181 DBG("%s: blit failure\n", __func__); 182 return false; 183 } 184 185 if (ctx->Query.CurrentOcclusionObject) 186 ctx->Query.CurrentOcclusionObject->Result += width * height; 187 188out: 189 190 DBG("%s: success\n", __func__); 191 return true; 192} 193 194 195void 196intelCopyPixels(struct gl_context * ctx, 197 GLint srcx, GLint srcy, 198 GLsizei width, GLsizei height, 199 GLint destx, GLint desty, GLenum type) 200{ 201 DBG("%s\n", __func__); 202 203 if (!_mesa_check_conditional_render(ctx)) 204 return; 205 206 if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) 207 return; 208 209 /* this will use swrast if needed */ 210 _mesa_meta_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type); 211} 212