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 "brw_buffers.h"
36 #include "brw_mipmap_tree.h"
37 #include "brw_pixel.h"
38 #include "brw_fbo.h"
39 #include "brw_blit.h"
40 #include "brw_batch.h"
41 
42 #define FILE_DEBUG_FLAG DEBUG_PIXEL
43 
44 /**
45  * CopyPixels with the blitter.  Don't support zooming, pixel transfer, etc.
46  */
47 static bool
do_blit_copypixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint dstx,GLint dsty,GLenum type)48 do_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 brw_renderbuffer *draw_irb = NULL;
61    struct brw_renderbuffer *read_irb = NULL;
62 
63    /* Update draw buffer bounds */
64    _mesa_update_state(ctx);
65 
66    brw_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 = brw_renderbuffer(fb->_ColorDrawBuffers[0]);
76       read_irb = brw_renderbuffer(read_fb->_ColorReadBuffer);
77       break;
78    case GL_DEPTH_STENCIL_EXT:
79       draw_irb = brw_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
80       read_irb =
81          brw_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    brw_batch_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 (!brw_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 
186 out:
187 
188    DBG("%s: success\n", __func__);
189    return true;
190 }
191 
192 
193 void
brw_copypixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint destx,GLint desty,GLenum type)194 brw_copypixels(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.ver < 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