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  */
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 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 (!ctx->Color.ColorMask[0][0] ||
138        !ctx->Color.ColorMask[0][1] ||
139        !ctx->Color.ColorMask[0][2] ||
140        !ctx->Color.ColorMask[0][3]) {
141       perf_debug("glCopyPixels(): Unsupported color mask state\n");
142       return false;
143    }
144 
145    if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) {
146       perf_debug("glCopyPixels(): Unsupported pixel zoom\n");
147       return false;
148    }
149 
150    intel_batchbuffer_flush(brw);
151 
152    /* Clip to destination buffer. */
153    orig_dstx = dstx;
154    orig_dsty = dsty;
155    if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
156 			     fb->_Xmax, fb->_Ymax,
157 			     &dstx, &dsty, &width, &height))
158       goto out;
159    /* Adjust src coords for our post-clipped destination origin */
160    srcx += dstx - orig_dstx;
161    srcy += dsty - orig_dsty;
162 
163    /* Clip to source buffer. */
164    orig_srcx = srcx;
165    orig_srcy = srcy;
166    if (!_mesa_clip_to_region(0, 0,
167 			     read_fb->Width, read_fb->Height,
168 			     &srcx, &srcy, &width, &height))
169       goto out;
170    /* Adjust dst coords for our post-clipped source origin */
171    dstx += srcx - orig_srcx;
172    dsty += srcy - orig_srcy;
173 
174    if (!intel_miptree_blit(brw,
175                            read_irb->mt, read_irb->mt_level, read_irb->mt_layer,
176                            srcx, srcy, _mesa_is_winsys_fbo(read_fb),
177                            draw_irb->mt, draw_irb->mt_level, draw_irb->mt_layer,
178                            dstx, dsty, _mesa_is_winsys_fbo(fb),
179                            width, height,
180                            (ctx->Color.ColorLogicOpEnabled ?
181                             ctx->Color.LogicOp : GL_COPY))) {
182       DBG("%s: blit failure\n", __func__);
183       return false;
184    }
185 
186    if (ctx->Query.CurrentOcclusionObject)
187       ctx->Query.CurrentOcclusionObject->Result += width * height;
188 
189 out:
190 
191    DBG("%s: success\n", __func__);
192    return true;
193 }
194 
195 
196 void
intelCopyPixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint destx,GLint desty,GLenum type)197 intelCopyPixels(struct gl_context * ctx,
198                 GLint srcx, GLint srcy,
199                 GLsizei width, GLsizei height,
200                 GLint destx, GLint desty, GLenum type)
201 {
202    DBG("%s\n", __func__);
203 
204    if (!_mesa_check_conditional_render(ctx))
205       return;
206 
207    if (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