xref: /aosp_15_r20/external/mesa3d/src/mesa/main/blit.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Mesa 3-D graphics library
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker  * Copyright (C) 1999-2013  VMware, Inc.  All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
9*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
10*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
12*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
15*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
16*61046927SAndroid Build Coastguard Worker  *
17*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23*61046927SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
24*61046927SAndroid Build Coastguard Worker  */
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker /*
27*61046927SAndroid Build Coastguard Worker  * glBlitFramebuffer functions.
28*61046927SAndroid Build Coastguard Worker  */
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
31*61046927SAndroid Build Coastguard Worker #include <stdio.h>
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "context.h"
34*61046927SAndroid Build Coastguard Worker #include "enums.h"
35*61046927SAndroid Build Coastguard Worker #include "blit.h"
36*61046927SAndroid Build Coastguard Worker #include "fbobject.h"
37*61046927SAndroid Build Coastguard Worker #include "framebuffer.h"
38*61046927SAndroid Build Coastguard Worker #include "glformats.h"
39*61046927SAndroid Build Coastguard Worker #include "image.h"
40*61046927SAndroid Build Coastguard Worker #include "mtypes.h"
41*61046927SAndroid Build Coastguard Worker #include "macros.h"
42*61046927SAndroid Build Coastguard Worker #include "readpix.h"
43*61046927SAndroid Build Coastguard Worker #include "renderbuffer.h"
44*61046927SAndroid Build Coastguard Worker #include "state.h"
45*61046927SAndroid Build Coastguard Worker #include "api_exec_decl.h"
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_cb_bitmap.h"
48*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_cb_texture.h"
49*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_manager.h"
50*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_context.h"
51*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_scissor.h"
52*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_texture.h"
53*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_util.h"
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker /** Set this to 1 to debug/log glBlitFramebuffer() calls */
56*61046927SAndroid Build Coastguard Worker #define DEBUG_BLIT 0
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker static const struct gl_renderbuffer_attachment *
find_attachment(const struct gl_framebuffer * fb,const struct gl_renderbuffer * rb)61*61046927SAndroid Build Coastguard Worker find_attachment(const struct gl_framebuffer *fb,
62*61046927SAndroid Build Coastguard Worker                 const struct gl_renderbuffer *rb)
63*61046927SAndroid Build Coastguard Worker {
64*61046927SAndroid Build Coastguard Worker    GLuint i;
65*61046927SAndroid Build Coastguard Worker    for (i = 0; i < ARRAY_SIZE(fb->Attachment); i++) {
66*61046927SAndroid Build Coastguard Worker       if (fb->Attachment[i].Renderbuffer == rb)
67*61046927SAndroid Build Coastguard Worker          return &fb->Attachment[i];
68*61046927SAndroid Build Coastguard Worker    }
69*61046927SAndroid Build Coastguard Worker    return NULL;
70*61046927SAndroid Build Coastguard Worker }
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker /**
74*61046927SAndroid Build Coastguard Worker  * \return true if two regions overlap, false otherwise
75*61046927SAndroid Build Coastguard Worker  */
76*61046927SAndroid Build Coastguard Worker bool
_mesa_regions_overlap(int srcX0,int srcY0,int srcX1,int srcY1,int dstX0,int dstY0,int dstX1,int dstY1)77*61046927SAndroid Build Coastguard Worker _mesa_regions_overlap(int srcX0, int srcY0,
78*61046927SAndroid Build Coastguard Worker                       int srcX1, int srcY1,
79*61046927SAndroid Build Coastguard Worker                       int dstX0, int dstY0,
80*61046927SAndroid Build Coastguard Worker                       int dstX1, int dstY1)
81*61046927SAndroid Build Coastguard Worker {
82*61046927SAndroid Build Coastguard Worker    if (MAX2(srcX0, srcX1) <= MIN2(dstX0, dstX1))
83*61046927SAndroid Build Coastguard Worker       return false; /* dst completely right of src */
84*61046927SAndroid Build Coastguard Worker 
85*61046927SAndroid Build Coastguard Worker    if (MAX2(dstX0, dstX1) <= MIN2(srcX0, srcX1))
86*61046927SAndroid Build Coastguard Worker       return false; /* dst completely left of src */
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker    if (MAX2(srcY0, srcY1) <= MIN2(dstY0, dstY1))
89*61046927SAndroid Build Coastguard Worker       return false; /* dst completely above src */
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    if (MAX2(dstY0, dstY1) <= MIN2(srcY0, srcY1))
92*61046927SAndroid Build Coastguard Worker       return false; /* dst completely below src */
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker    return true; /* some overlap */
95*61046927SAndroid Build Coastguard Worker }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker /**
99*61046927SAndroid Build Coastguard Worker  * Helper function for checking if the datatypes of color buffers are
100*61046927SAndroid Build Coastguard Worker  * compatible for glBlitFramebuffer.  From the 3.1 spec, page 198:
101*61046927SAndroid Build Coastguard Worker  *
102*61046927SAndroid Build Coastguard Worker  * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
103*61046927SAndroid Build Coastguard Worker  *  and any of the following conditions hold:
104*61046927SAndroid Build Coastguard Worker  *   - The read buffer contains fixed-point or floating-point values and any
105*61046927SAndroid Build Coastguard Worker  *     draw buffer contains neither fixed-point nor floating-point values.
106*61046927SAndroid Build Coastguard Worker  *   - The read buffer contains unsigned integer values and any draw buffer
107*61046927SAndroid Build Coastguard Worker  *     does not contain unsigned integer values.
108*61046927SAndroid Build Coastguard Worker  *   - The read buffer contains signed integer values and any draw buffer
109*61046927SAndroid Build Coastguard Worker  *     does not contain signed integer values."
110*61046927SAndroid Build Coastguard Worker  */
111*61046927SAndroid Build Coastguard Worker static GLboolean
compatible_color_datatypes(mesa_format srcFormat,mesa_format dstFormat)112*61046927SAndroid Build Coastguard Worker compatible_color_datatypes(mesa_format srcFormat, mesa_format dstFormat)
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker    GLenum srcType = _mesa_get_format_datatype(srcFormat);
115*61046927SAndroid Build Coastguard Worker    GLenum dstType = _mesa_get_format_datatype(dstFormat);
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
118*61046927SAndroid Build Coastguard Worker       assert(srcType == GL_UNSIGNED_NORMALIZED ||
119*61046927SAndroid Build Coastguard Worker              srcType == GL_SIGNED_NORMALIZED ||
120*61046927SAndroid Build Coastguard Worker              srcType == GL_FLOAT);
121*61046927SAndroid Build Coastguard Worker       /* Boil any of those types down to GL_FLOAT */
122*61046927SAndroid Build Coastguard Worker       srcType = GL_FLOAT;
123*61046927SAndroid Build Coastguard Worker    }
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker    if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
126*61046927SAndroid Build Coastguard Worker       assert(dstType == GL_UNSIGNED_NORMALIZED ||
127*61046927SAndroid Build Coastguard Worker              dstType == GL_SIGNED_NORMALIZED ||
128*61046927SAndroid Build Coastguard Worker              dstType == GL_FLOAT);
129*61046927SAndroid Build Coastguard Worker       /* Boil any of those types down to GL_FLOAT */
130*61046927SAndroid Build Coastguard Worker       dstType = GL_FLOAT;
131*61046927SAndroid Build Coastguard Worker    }
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker    return srcType == dstType;
134*61046927SAndroid Build Coastguard Worker }
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker static GLboolean
compatible_resolve_formats(const struct gl_renderbuffer * readRb,const struct gl_renderbuffer * drawRb)138*61046927SAndroid Build Coastguard Worker compatible_resolve_formats(const struct gl_renderbuffer *readRb,
139*61046927SAndroid Build Coastguard Worker                            const struct gl_renderbuffer *drawRb)
140*61046927SAndroid Build Coastguard Worker {
141*61046927SAndroid Build Coastguard Worker    GLenum readFormat, drawFormat;
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker    /* This checks whether the internal formats are compatible rather than the
144*61046927SAndroid Build Coastguard Worker     * Mesa format for two reasons:
145*61046927SAndroid Build Coastguard Worker     *
146*61046927SAndroid Build Coastguard Worker     * • Under some circumstances, the user may request e.g. two GL_RGBA8
147*61046927SAndroid Build Coastguard Worker     *   textures and get two entirely different Mesa formats like RGBA8888 and
148*61046927SAndroid Build Coastguard Worker     *   ARGB8888. Drivers behaving like that should be able to cope with
149*61046927SAndroid Build Coastguard Worker     *   non-matching formats by themselves, because it's not the user's fault.
150*61046927SAndroid Build Coastguard Worker     *
151*61046927SAndroid Build Coastguard Worker     * • Picking two different internal formats can end up with the same Mesa
152*61046927SAndroid Build Coastguard Worker     *   format. For example the driver might be simulating GL_RGB textures
153*61046927SAndroid Build Coastguard Worker     *   with GL_RGBA internally and in that case both internal formats would
154*61046927SAndroid Build Coastguard Worker     *   end up with RGBA8888.
155*61046927SAndroid Build Coastguard Worker     *
156*61046927SAndroid Build Coastguard Worker     * This function is used to generate a GL error according to the spec so in
157*61046927SAndroid Build Coastguard Worker     * both cases we want to be looking at the application-level format, which
158*61046927SAndroid Build Coastguard Worker     * is InternalFormat.
159*61046927SAndroid Build Coastguard Worker     *
160*61046927SAndroid Build Coastguard Worker     * Blits between linear and sRGB formats are also allowed.
161*61046927SAndroid Build Coastguard Worker     */
162*61046927SAndroid Build Coastguard Worker    readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
163*61046927SAndroid Build Coastguard Worker    drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
164*61046927SAndroid Build Coastguard Worker    readFormat = _mesa_get_linear_internalformat(readFormat);
165*61046927SAndroid Build Coastguard Worker    drawFormat = _mesa_get_linear_internalformat(drawFormat);
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    if (readFormat == drawFormat) {
168*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
169*61046927SAndroid Build Coastguard Worker    }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    return GL_FALSE;
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker static GLboolean
is_valid_blit_filter(const struct gl_context * ctx,GLenum filter)176*61046927SAndroid Build Coastguard Worker is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
177*61046927SAndroid Build Coastguard Worker {
178*61046927SAndroid Build Coastguard Worker    switch (filter) {
179*61046927SAndroid Build Coastguard Worker    case GL_NEAREST:
180*61046927SAndroid Build Coastguard Worker    case GL_LINEAR:
181*61046927SAndroid Build Coastguard Worker       return true;
182*61046927SAndroid Build Coastguard Worker    case GL_SCALED_RESOLVE_FASTEST_EXT:
183*61046927SAndroid Build Coastguard Worker    case GL_SCALED_RESOLVE_NICEST_EXT:
184*61046927SAndroid Build Coastguard Worker       return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled;
185*61046927SAndroid Build Coastguard Worker    default:
186*61046927SAndroid Build Coastguard Worker       return false;
187*61046927SAndroid Build Coastguard Worker    }
188*61046927SAndroid Build Coastguard Worker }
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker static bool
validate_color_buffer(struct gl_context * ctx,struct gl_framebuffer * readFb,struct gl_framebuffer * drawFb,GLenum filter,const char * func)192*61046927SAndroid Build Coastguard Worker validate_color_buffer(struct gl_context *ctx, struct gl_framebuffer *readFb,
193*61046927SAndroid Build Coastguard Worker                       struct gl_framebuffer *drawFb, GLenum filter,
194*61046927SAndroid Build Coastguard Worker                       const char *func)
195*61046927SAndroid Build Coastguard Worker {
196*61046927SAndroid Build Coastguard Worker    const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
197*61046927SAndroid Build Coastguard Worker    const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
198*61046927SAndroid Build Coastguard Worker    const struct gl_renderbuffer *colorDrawRb = NULL;
199*61046927SAndroid Build Coastguard Worker    GLuint i;
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker    for (i = 0; i < numColorDrawBuffers; i++) {
202*61046927SAndroid Build Coastguard Worker       colorDrawRb = drawFb->_ColorDrawBuffers[i];
203*61046927SAndroid Build Coastguard Worker       if (!colorDrawRb)
204*61046927SAndroid Build Coastguard Worker          continue;
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker       /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
207*61046927SAndroid Build Coastguard Worker        * ES 3.0.1 spec says:
208*61046927SAndroid Build Coastguard Worker        *
209*61046927SAndroid Build Coastguard Worker        *     "If the source and destination buffers are identical, an
210*61046927SAndroid Build Coastguard Worker        *     INVALID_OPERATION error is generated. Different mipmap levels of a
211*61046927SAndroid Build Coastguard Worker        *     texture, different layers of a three- dimensional texture or
212*61046927SAndroid Build Coastguard Worker        *     two-dimensional array texture, and different faces of a cube map
213*61046927SAndroid Build Coastguard Worker        *     texture do not constitute identical buffers."
214*61046927SAndroid Build Coastguard Worker        */
215*61046927SAndroid Build Coastguard Worker       if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
216*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
217*61046927SAndroid Build Coastguard Worker                      "%s(source and destination color buffer cannot be the "
218*61046927SAndroid Build Coastguard Worker                      "same)", func);
219*61046927SAndroid Build Coastguard Worker          return false;
220*61046927SAndroid Build Coastguard Worker       }
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker       if (!compatible_color_datatypes(colorReadRb->Format,
223*61046927SAndroid Build Coastguard Worker                                       colorDrawRb->Format)) {
224*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
225*61046927SAndroid Build Coastguard Worker                      "%s(color buffer datatypes mismatch)", func);
226*61046927SAndroid Build Coastguard Worker          return false;
227*61046927SAndroid Build Coastguard Worker       }
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker       /* extra checks for multisample copies... */
230*61046927SAndroid Build Coastguard Worker       if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
231*61046927SAndroid Build Coastguard Worker          /* color formats must match on GLES. This isn't checked on desktop GL
232*61046927SAndroid Build Coastguard Worker           * because the GL 4.4 spec was changed to allow it.  In the section
233*61046927SAndroid Build Coastguard Worker           * entitled “Changes in the released
234*61046927SAndroid Build Coastguard Worker           * Specification of July 22, 2013” it says:
235*61046927SAndroid Build Coastguard Worker           *
236*61046927SAndroid Build Coastguard Worker           * “Relax BlitFramebuffer in section 18.3.1 so that format conversion
237*61046927SAndroid Build Coastguard Worker           * can take place during multisample blits, since drivers already
238*61046927SAndroid Build Coastguard Worker           * allow this and some apps depend on it.”
239*61046927SAndroid Build Coastguard Worker           */
240*61046927SAndroid Build Coastguard Worker          if (_mesa_is_gles(ctx) &&
241*61046927SAndroid Build Coastguard Worker              !compatible_resolve_formats(colorReadRb, colorDrawRb)) {
242*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, GL_INVALID_OPERATION,
243*61046927SAndroid Build Coastguard Worker                         "%s(bad src/dst multisample pixel formats)", func);
244*61046927SAndroid Build Coastguard Worker             return false;
245*61046927SAndroid Build Coastguard Worker          }
246*61046927SAndroid Build Coastguard Worker       }
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker    }
249*61046927SAndroid Build Coastguard Worker 
250*61046927SAndroid Build Coastguard Worker    if (filter != GL_NEAREST) {
251*61046927SAndroid Build Coastguard Worker       /* From EXT_framebuffer_multisample_blit_scaled specification:
252*61046927SAndroid Build Coastguard Worker        * "Calling BlitFramebuffer will result in an INVALID_OPERATION error if
253*61046927SAndroid Build Coastguard Worker        * filter is not NEAREST and read buffer contains integer data."
254*61046927SAndroid Build Coastguard Worker        */
255*61046927SAndroid Build Coastguard Worker       GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
256*61046927SAndroid Build Coastguard Worker       if (type == GL_INT || type == GL_UNSIGNED_INT) {
257*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
258*61046927SAndroid Build Coastguard Worker                      "%s(integer color type)", func);
259*61046927SAndroid Build Coastguard Worker          return false;
260*61046927SAndroid Build Coastguard Worker       }
261*61046927SAndroid Build Coastguard Worker    }
262*61046927SAndroid Build Coastguard Worker    return true;
263*61046927SAndroid Build Coastguard Worker }
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker static bool
validate_stencil_buffer(struct gl_context * ctx,struct gl_framebuffer * readFb,struct gl_framebuffer * drawFb,const char * func)267*61046927SAndroid Build Coastguard Worker validate_stencil_buffer(struct gl_context *ctx, struct gl_framebuffer *readFb,
268*61046927SAndroid Build Coastguard Worker                         struct gl_framebuffer *drawFb, const char *func)
269*61046927SAndroid Build Coastguard Worker {
270*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *readRb =
271*61046927SAndroid Build Coastguard Worker       readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
272*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *drawRb =
273*61046927SAndroid Build Coastguard Worker       drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
274*61046927SAndroid Build Coastguard Worker    int read_z_bits, draw_z_bits;
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker    if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
277*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
278*61046927SAndroid Build Coastguard Worker                   "%s(source and destination stencil buffer cannot be the "
279*61046927SAndroid Build Coastguard Worker                   "same)", func);
280*61046927SAndroid Build Coastguard Worker       return false;
281*61046927SAndroid Build Coastguard Worker    }
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker    if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
284*61046927SAndroid Build Coastguard Worker        _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
285*61046927SAndroid Build Coastguard Worker       /* There is no need to check the stencil datatype here, because
286*61046927SAndroid Build Coastguard Worker        * there is only one: GL_UNSIGNED_INT.
287*61046927SAndroid Build Coastguard Worker        */
288*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
289*61046927SAndroid Build Coastguard Worker                   "%s(stencil attachment format mismatch)", func);
290*61046927SAndroid Build Coastguard Worker       return false;
291*61046927SAndroid Build Coastguard Worker    }
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker    read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
294*61046927SAndroid Build Coastguard Worker    draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker    /* If both buffers also have depth data, the depth formats must match
297*61046927SAndroid Build Coastguard Worker     * as well.  If one doesn't have depth, it's not blitted, so we should
298*61046927SAndroid Build Coastguard Worker     * ignore the depth format check.
299*61046927SAndroid Build Coastguard Worker     */
300*61046927SAndroid Build Coastguard Worker    if (read_z_bits > 0 && draw_z_bits > 0 &&
301*61046927SAndroid Build Coastguard Worker        (read_z_bits != draw_z_bits ||
302*61046927SAndroid Build Coastguard Worker         _mesa_get_format_datatype(readRb->Format) !=
303*61046927SAndroid Build Coastguard Worker         _mesa_get_format_datatype(drawRb->Format))) {
304*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
305*61046927SAndroid Build Coastguard Worker                   "%s(stencil attachment depth format mismatch)", func);
306*61046927SAndroid Build Coastguard Worker       return false;
307*61046927SAndroid Build Coastguard Worker    }
308*61046927SAndroid Build Coastguard Worker    return true;
309*61046927SAndroid Build Coastguard Worker }
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker static bool
validate_depth_buffer(struct gl_context * ctx,struct gl_framebuffer * readFb,struct gl_framebuffer * drawFb,const char * func)313*61046927SAndroid Build Coastguard Worker validate_depth_buffer(struct gl_context *ctx, struct gl_framebuffer *readFb,
314*61046927SAndroid Build Coastguard Worker                       struct gl_framebuffer *drawFb, const char *func)
315*61046927SAndroid Build Coastguard Worker {
316*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *readRb =
317*61046927SAndroid Build Coastguard Worker       readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
318*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *drawRb =
319*61046927SAndroid Build Coastguard Worker       drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
320*61046927SAndroid Build Coastguard Worker    int read_s_bit, draw_s_bit;
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker    if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
323*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
324*61046927SAndroid Build Coastguard Worker                   "%s(source and destination depth buffer cannot be the same)",
325*61046927SAndroid Build Coastguard Worker                   func);
326*61046927SAndroid Build Coastguard Worker       return false;
327*61046927SAndroid Build Coastguard Worker    }
328*61046927SAndroid Build Coastguard Worker 
329*61046927SAndroid Build Coastguard Worker    if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
330*61046927SAndroid Build Coastguard Worker         _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
331*61046927SAndroid Build Coastguard Worker        (_mesa_get_format_datatype(readRb->Format) !=
332*61046927SAndroid Build Coastguard Worker         _mesa_get_format_datatype(drawRb->Format))) {
333*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
334*61046927SAndroid Build Coastguard Worker                   "%s(depth attachment format mismatch)", func);
335*61046927SAndroid Build Coastguard Worker       return false;
336*61046927SAndroid Build Coastguard Worker    }
337*61046927SAndroid Build Coastguard Worker 
338*61046927SAndroid Build Coastguard Worker    read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
339*61046927SAndroid Build Coastguard Worker    draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
340*61046927SAndroid Build Coastguard Worker 
341*61046927SAndroid Build Coastguard Worker    /* If both buffers also have stencil data, the stencil formats must match as
342*61046927SAndroid Build Coastguard Worker     * well.  If one doesn't have stencil, it's not blitted, so we should ignore
343*61046927SAndroid Build Coastguard Worker     * the stencil format check.
344*61046927SAndroid Build Coastguard Worker     */
345*61046927SAndroid Build Coastguard Worker    if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
346*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
347*61046927SAndroid Build Coastguard Worker                   "%s(depth attachment stencil bits mismatch)", func);
348*61046927SAndroid Build Coastguard Worker       return false;
349*61046927SAndroid Build Coastguard Worker    }
350*61046927SAndroid Build Coastguard Worker    return true;
351*61046927SAndroid Build Coastguard Worker }
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker static void
do_blit_framebuffer(struct gl_context * ctx,struct gl_framebuffer * readFB,struct gl_framebuffer * drawFB,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)355*61046927SAndroid Build Coastguard Worker do_blit_framebuffer(struct gl_context *ctx,
356*61046927SAndroid Build Coastguard Worker                     struct gl_framebuffer *readFB,
357*61046927SAndroid Build Coastguard Worker                     struct gl_framebuffer *drawFB,
358*61046927SAndroid Build Coastguard Worker                     GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
359*61046927SAndroid Build Coastguard Worker                     GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
360*61046927SAndroid Build Coastguard Worker                     GLbitfield mask, GLenum filter)
361*61046927SAndroid Build Coastguard Worker {
362*61046927SAndroid Build Coastguard Worker    struct st_context *st = st_context(ctx);
363*61046927SAndroid Build Coastguard Worker    const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
364*61046927SAndroid Build Coastguard Worker                                     GL_STENCIL_BUFFER_BIT);
365*61046927SAndroid Build Coastguard Worker    const uint pFilter = ((filter == GL_NEAREST)
366*61046927SAndroid Build Coastguard Worker                          ? PIPE_TEX_FILTER_NEAREST
367*61046927SAndroid Build Coastguard Worker                          : PIPE_TEX_FILTER_LINEAR);
368*61046927SAndroid Build Coastguard Worker    struct {
369*61046927SAndroid Build Coastguard Worker       GLint srcX0, srcY0, srcX1, srcY1;
370*61046927SAndroid Build Coastguard Worker       GLint dstX0, dstY0, dstX1, dstY1;
371*61046927SAndroid Build Coastguard Worker    } clip;
372*61046927SAndroid Build Coastguard Worker    struct pipe_blit_info blit;
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    st_manager_validate_framebuffers(st);
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    /* Make sure bitmap rendering has landed in the framebuffers */
377*61046927SAndroid Build Coastguard Worker    st_flush_bitmap_cache(st);
378*61046927SAndroid Build Coastguard Worker    st_invalidate_readpix_cache(st);
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker    clip.srcX0 = srcX0;
381*61046927SAndroid Build Coastguard Worker    clip.srcY0 = srcY0;
382*61046927SAndroid Build Coastguard Worker    clip.srcX1 = srcX1;
383*61046927SAndroid Build Coastguard Worker    clip.srcY1 = srcY1;
384*61046927SAndroid Build Coastguard Worker    clip.dstX0 = dstX0;
385*61046927SAndroid Build Coastguard Worker    clip.dstY0 = dstY0;
386*61046927SAndroid Build Coastguard Worker    clip.dstX1 = dstX1;
387*61046927SAndroid Build Coastguard Worker    clip.dstY1 = dstY1;
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    /* NOTE: If the src and dst dimensions don't match, we cannot simply adjust
390*61046927SAndroid Build Coastguard Worker     * the integer coordinates to account for clipping (or scissors) because that
391*61046927SAndroid Build Coastguard Worker     * would make us cut off fractional parts, affecting the result of the blit.
392*61046927SAndroid Build Coastguard Worker     *
393*61046927SAndroid Build Coastguard Worker     * XXX: This should depend on mask !
394*61046927SAndroid Build Coastguard Worker     */
395*61046927SAndroid Build Coastguard Worker    if (!_mesa_clip_blit(ctx, readFB, drawFB,
396*61046927SAndroid Build Coastguard Worker                         &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
397*61046927SAndroid Build Coastguard Worker                         &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
398*61046927SAndroid Build Coastguard Worker       return; /* nothing to draw/blit */
399*61046927SAndroid Build Coastguard Worker    }
400*61046927SAndroid Build Coastguard Worker    memset(&blit, 0, sizeof(struct pipe_blit_info));
401*61046927SAndroid Build Coastguard Worker    blit.scissor_enable =
402*61046927SAndroid Build Coastguard Worker       (dstX0 != clip.dstX0) ||
403*61046927SAndroid Build Coastguard Worker       (dstY0 != clip.dstY0) ||
404*61046927SAndroid Build Coastguard Worker       (dstX1 != clip.dstX1) ||
405*61046927SAndroid Build Coastguard Worker       (dstY1 != clip.dstY1);
406*61046927SAndroid Build Coastguard Worker 
407*61046927SAndroid Build Coastguard Worker    if (_mesa_fb_orientation(drawFB) == Y_0_TOP) {
408*61046927SAndroid Build Coastguard Worker       /* invert Y for dest */
409*61046927SAndroid Build Coastguard Worker       dstY0 = drawFB->Height - dstY0;
410*61046927SAndroid Build Coastguard Worker       dstY1 = drawFB->Height - dstY1;
411*61046927SAndroid Build Coastguard Worker       /* invert Y for clip */
412*61046927SAndroid Build Coastguard Worker       clip.dstY0 = drawFB->Height - clip.dstY0;
413*61046927SAndroid Build Coastguard Worker       clip.dstY1 = drawFB->Height - clip.dstY1;
414*61046927SAndroid Build Coastguard Worker    }
415*61046927SAndroid Build Coastguard Worker    if (blit.scissor_enable) {
416*61046927SAndroid Build Coastguard Worker       blit.scissor.minx = MIN2(clip.dstX0, clip.dstX1);
417*61046927SAndroid Build Coastguard Worker       blit.scissor.miny = MIN2(clip.dstY0, clip.dstY1);
418*61046927SAndroid Build Coastguard Worker       blit.scissor.maxx = MAX2(clip.dstX0, clip.dstX1);
419*61046927SAndroid Build Coastguard Worker       blit.scissor.maxy = MAX2(clip.dstY0, clip.dstY1);
420*61046927SAndroid Build Coastguard Worker #if 0
421*61046927SAndroid Build Coastguard Worker       debug_printf("scissor = (%i,%i)-(%i,%i)\n",
422*61046927SAndroid Build Coastguard Worker                    blit.scissor.minx,blit.scissor.miny,
423*61046927SAndroid Build Coastguard Worker                    blit.scissor.maxx,blit.scissor.maxy);
424*61046927SAndroid Build Coastguard Worker #endif
425*61046927SAndroid Build Coastguard Worker    }
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker    if (_mesa_fb_orientation(readFB) == Y_0_TOP) {
428*61046927SAndroid Build Coastguard Worker       /* invert Y for src */
429*61046927SAndroid Build Coastguard Worker       srcY0 = readFB->Height - srcY0;
430*61046927SAndroid Build Coastguard Worker       srcY1 = readFB->Height - srcY1;
431*61046927SAndroid Build Coastguard Worker    }
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker    if (srcY0 > srcY1 && dstY0 > dstY1) {
434*61046927SAndroid Build Coastguard Worker       /* Both src and dst are upside down.  Swap Y to make it
435*61046927SAndroid Build Coastguard Worker        * right-side up to increase odds of using a fast path.
436*61046927SAndroid Build Coastguard Worker        * Recall that all Gallium raster coords have Y=0=top.
437*61046927SAndroid Build Coastguard Worker        */
438*61046927SAndroid Build Coastguard Worker       GLint tmp;
439*61046927SAndroid Build Coastguard Worker       tmp = srcY0;
440*61046927SAndroid Build Coastguard Worker       srcY0 = srcY1;
441*61046927SAndroid Build Coastguard Worker       srcY1 = tmp;
442*61046927SAndroid Build Coastguard Worker       tmp = dstY0;
443*61046927SAndroid Build Coastguard Worker       dstY0 = dstY1;
444*61046927SAndroid Build Coastguard Worker       dstY1 = tmp;
445*61046927SAndroid Build Coastguard Worker    }
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker    blit.src.box.depth = 1;
448*61046927SAndroid Build Coastguard Worker    blit.dst.box.depth = 1;
449*61046927SAndroid Build Coastguard Worker 
450*61046927SAndroid Build Coastguard Worker    /* Destination dimensions have to be positive: */
451*61046927SAndroid Build Coastguard Worker    if (dstX0 < dstX1) {
452*61046927SAndroid Build Coastguard Worker       blit.dst.box.x = dstX0;
453*61046927SAndroid Build Coastguard Worker       blit.src.box.x = srcX0;
454*61046927SAndroid Build Coastguard Worker       blit.dst.box.width = dstX1 - dstX0;
455*61046927SAndroid Build Coastguard Worker       blit.src.box.width = srcX1 - srcX0;
456*61046927SAndroid Build Coastguard Worker    } else {
457*61046927SAndroid Build Coastguard Worker       blit.dst.box.x = dstX1;
458*61046927SAndroid Build Coastguard Worker       blit.src.box.x = srcX1;
459*61046927SAndroid Build Coastguard Worker       blit.dst.box.width = dstX0 - dstX1;
460*61046927SAndroid Build Coastguard Worker       blit.src.box.width = srcX0 - srcX1;
461*61046927SAndroid Build Coastguard Worker    }
462*61046927SAndroid Build Coastguard Worker    if (dstY0 < dstY1) {
463*61046927SAndroid Build Coastguard Worker       blit.dst.box.y = dstY0;
464*61046927SAndroid Build Coastguard Worker       blit.src.box.y = srcY0;
465*61046927SAndroid Build Coastguard Worker       blit.dst.box.height = dstY1 - dstY0;
466*61046927SAndroid Build Coastguard Worker       blit.src.box.height = srcY1 - srcY0;
467*61046927SAndroid Build Coastguard Worker    } else {
468*61046927SAndroid Build Coastguard Worker       blit.dst.box.y = dstY1;
469*61046927SAndroid Build Coastguard Worker       blit.src.box.y = srcY1;
470*61046927SAndroid Build Coastguard Worker       blit.dst.box.height = dstY0 - dstY1;
471*61046927SAndroid Build Coastguard Worker       blit.src.box.height = srcY0 - srcY1;
472*61046927SAndroid Build Coastguard Worker    }
473*61046927SAndroid Build Coastguard Worker 
474*61046927SAndroid Build Coastguard Worker    if (drawFB != ctx->WinSysDrawBuffer)
475*61046927SAndroid Build Coastguard Worker       st_window_rectangles_to_blit(ctx, &blit);
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker    blit.filter = pFilter;
478*61046927SAndroid Build Coastguard Worker    blit.render_condition_enable = st->has_conditional_render;
479*61046927SAndroid Build Coastguard Worker    blit.alpha_blend = false;
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker    if (mask & GL_COLOR_BUFFER_BIT) {
482*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer_attachment *srcAtt =
483*61046927SAndroid Build Coastguard Worker          &readFB->Attachment[readFB->_ColorReadBufferIndex];
484*61046927SAndroid Build Coastguard Worker       GLuint i;
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker       blit.mask = PIPE_MASK_RGBA;
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker       if (srcAtt->Type == GL_TEXTURE) {
489*61046927SAndroid Build Coastguard Worker          /* Make sure that the st_texture_object->pt is the current storage for
490*61046927SAndroid Build Coastguard Worker           * our miplevel.  The finalize would happen at some point anyway, might
491*61046927SAndroid Build Coastguard Worker           * as well be now.
492*61046927SAndroid Build Coastguard Worker           */
493*61046927SAndroid Build Coastguard Worker          st_finalize_texture(ctx, ctx->pipe, srcAtt->Texture, srcAtt->CubeMapFace);
494*61046927SAndroid Build Coastguard Worker 
495*61046927SAndroid Build Coastguard Worker          struct gl_texture_object *srcObj = srcAtt->Texture;
496*61046927SAndroid Build Coastguard Worker 
497*61046927SAndroid Build Coastguard Worker          if (!srcObj || !srcObj->pt) {
498*61046927SAndroid Build Coastguard Worker             return;
499*61046927SAndroid Build Coastguard Worker          }
500*61046927SAndroid Build Coastguard Worker 
501*61046927SAndroid Build Coastguard Worker          blit.src.resource = srcObj->pt;
502*61046927SAndroid Build Coastguard Worker          blit.src.level = srcAtt->TextureLevel;
503*61046927SAndroid Build Coastguard Worker          blit.src.box.z = srcAtt->Zoffset + srcAtt->CubeMapFace;
504*61046927SAndroid Build Coastguard Worker          blit.src.format = srcObj->surface_based ? srcObj->surface_format : srcObj->pt->format;
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker          if (!ctx->Color.sRGBEnabled)
507*61046927SAndroid Build Coastguard Worker             blit.src.format = util_format_linear(blit.src.format);
508*61046927SAndroid Build Coastguard Worker       }
509*61046927SAndroid Build Coastguard Worker       else {
510*61046927SAndroid Build Coastguard Worker          struct gl_renderbuffer *srcRb = readFB->_ColorReadBuffer;
511*61046927SAndroid Build Coastguard Worker          struct pipe_surface *srcSurf;
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker          if (!srcRb)
514*61046927SAndroid Build Coastguard Worker             return;
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker          _mesa_update_renderbuffer_surface(ctx, srcRb);
517*61046927SAndroid Build Coastguard Worker 
518*61046927SAndroid Build Coastguard Worker          if (!srcRb->surface)
519*61046927SAndroid Build Coastguard Worker             return;
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker          srcSurf = srcRb->surface;
522*61046927SAndroid Build Coastguard Worker 
523*61046927SAndroid Build Coastguard Worker          blit.src.resource = srcSurf->texture;
524*61046927SAndroid Build Coastguard Worker          blit.src.level = srcSurf->u.tex.level;
525*61046927SAndroid Build Coastguard Worker          blit.src.box.z = srcSurf->u.tex.first_layer;
526*61046927SAndroid Build Coastguard Worker          blit.src.format = srcSurf->format;
527*61046927SAndroid Build Coastguard Worker       }
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker       for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
530*61046927SAndroid Build Coastguard Worker          struct gl_renderbuffer *dstRb = drawFB->_ColorDrawBuffers[i];
531*61046927SAndroid Build Coastguard Worker 
532*61046927SAndroid Build Coastguard Worker          if (dstRb) {
533*61046927SAndroid Build Coastguard Worker             struct pipe_surface *dstSurf;
534*61046927SAndroid Build Coastguard Worker 
535*61046927SAndroid Build Coastguard Worker             _mesa_update_renderbuffer_surface(ctx, dstRb);
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker             dstSurf = dstRb->surface;
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker             if (dstSurf) {
540*61046927SAndroid Build Coastguard Worker                blit.dst.resource = dstSurf->texture;
541*61046927SAndroid Build Coastguard Worker                blit.dst.level = dstSurf->u.tex.level;
542*61046927SAndroid Build Coastguard Worker                blit.dst.box.z = dstSurf->u.tex.first_layer;
543*61046927SAndroid Build Coastguard Worker                blit.dst.format = dstSurf->format;
544*61046927SAndroid Build Coastguard Worker 
545*61046927SAndroid Build Coastguard Worker                ctx->pipe->blit(ctx->pipe, &blit);
546*61046927SAndroid Build Coastguard Worker                dstRb->defined = true; /* front buffer tracking */
547*61046927SAndroid Build Coastguard Worker             }
548*61046927SAndroid Build Coastguard Worker          }
549*61046927SAndroid Build Coastguard Worker       }
550*61046927SAndroid Build Coastguard Worker    }
551*61046927SAndroid Build Coastguard Worker 
552*61046927SAndroid Build Coastguard Worker    if (mask & depthStencil) {
553*61046927SAndroid Build Coastguard Worker       /* depth and/or stencil blit */
554*61046927SAndroid Build Coastguard Worker 
555*61046927SAndroid Build Coastguard Worker       /* get src/dst depth surfaces */
556*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *srcDepthRb =
557*61046927SAndroid Build Coastguard Worker          readFB->Attachment[BUFFER_DEPTH].Renderbuffer;
558*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *dstDepthRb =
559*61046927SAndroid Build Coastguard Worker          drawFB->Attachment[BUFFER_DEPTH].Renderbuffer;
560*61046927SAndroid Build Coastguard Worker       struct pipe_surface *dstDepthSurf =
561*61046927SAndroid Build Coastguard Worker          dstDepthRb ? dstDepthRb->surface : NULL;
562*61046927SAndroid Build Coastguard Worker 
563*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *srcStencilRb =
564*61046927SAndroid Build Coastguard Worker          readFB->Attachment[BUFFER_STENCIL].Renderbuffer;
565*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *dstStencilRb =
566*61046927SAndroid Build Coastguard Worker          drawFB->Attachment[BUFFER_STENCIL].Renderbuffer;
567*61046927SAndroid Build Coastguard Worker       struct pipe_surface *dstStencilSurf =
568*61046927SAndroid Build Coastguard Worker          dstStencilRb ? dstStencilRb->surface : NULL;
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker       if (_mesa_has_depthstencil_combined(readFB) &&
571*61046927SAndroid Build Coastguard Worker           _mesa_has_depthstencil_combined(drawFB)) {
572*61046927SAndroid Build Coastguard Worker          blit.mask = 0;
573*61046927SAndroid Build Coastguard Worker          if (mask & GL_DEPTH_BUFFER_BIT)
574*61046927SAndroid Build Coastguard Worker             blit.mask |= PIPE_MASK_Z;
575*61046927SAndroid Build Coastguard Worker          if (mask & GL_STENCIL_BUFFER_BIT)
576*61046927SAndroid Build Coastguard Worker             blit.mask |= PIPE_MASK_S;
577*61046927SAndroid Build Coastguard Worker 
578*61046927SAndroid Build Coastguard Worker          blit.dst.resource = dstDepthSurf->texture;
579*61046927SAndroid Build Coastguard Worker          blit.dst.level = dstDepthSurf->u.tex.level;
580*61046927SAndroid Build Coastguard Worker          blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
581*61046927SAndroid Build Coastguard Worker          blit.dst.format = dstDepthSurf->format;
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker          blit.src.resource = srcDepthRb->texture;
584*61046927SAndroid Build Coastguard Worker          blit.src.level = srcDepthRb->surface->u.tex.level;
585*61046927SAndroid Build Coastguard Worker          blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
586*61046927SAndroid Build Coastguard Worker          blit.src.format = srcDepthRb->surface->format;
587*61046927SAndroid Build Coastguard Worker 
588*61046927SAndroid Build Coastguard Worker          ctx->pipe->blit(ctx->pipe, &blit);
589*61046927SAndroid Build Coastguard Worker       }
590*61046927SAndroid Build Coastguard Worker       else {
591*61046927SAndroid Build Coastguard Worker          /* blitting depth and stencil separately */
592*61046927SAndroid Build Coastguard Worker 
593*61046927SAndroid Build Coastguard Worker          if (mask & GL_DEPTH_BUFFER_BIT) {
594*61046927SAndroid Build Coastguard Worker             blit.mask = PIPE_MASK_Z;
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker             blit.dst.resource = dstDepthSurf->texture;
597*61046927SAndroid Build Coastguard Worker             blit.dst.level = dstDepthSurf->u.tex.level;
598*61046927SAndroid Build Coastguard Worker             blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
599*61046927SAndroid Build Coastguard Worker             blit.dst.format = dstDepthSurf->format;
600*61046927SAndroid Build Coastguard Worker 
601*61046927SAndroid Build Coastguard Worker             blit.src.resource = srcDepthRb->texture;
602*61046927SAndroid Build Coastguard Worker             blit.src.level = srcDepthRb->surface->u.tex.level;
603*61046927SAndroid Build Coastguard Worker             blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
604*61046927SAndroid Build Coastguard Worker             blit.src.format = srcDepthRb->surface->format;
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker             ctx->pipe->blit(ctx->pipe, &blit);
607*61046927SAndroid Build Coastguard Worker          }
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker          if (mask & GL_STENCIL_BUFFER_BIT) {
610*61046927SAndroid Build Coastguard Worker             blit.mask = PIPE_MASK_S;
611*61046927SAndroid Build Coastguard Worker 
612*61046927SAndroid Build Coastguard Worker             blit.dst.resource = dstStencilSurf->texture;
613*61046927SAndroid Build Coastguard Worker             blit.dst.level = dstStencilSurf->u.tex.level;
614*61046927SAndroid Build Coastguard Worker             blit.dst.box.z = dstStencilSurf->u.tex.first_layer;
615*61046927SAndroid Build Coastguard Worker             blit.dst.format = dstStencilSurf->format;
616*61046927SAndroid Build Coastguard Worker 
617*61046927SAndroid Build Coastguard Worker             blit.src.resource = srcStencilRb->texture;
618*61046927SAndroid Build Coastguard Worker             blit.src.level = srcStencilRb->surface->u.tex.level;
619*61046927SAndroid Build Coastguard Worker             blit.src.box.z = srcStencilRb->surface->u.tex.first_layer;
620*61046927SAndroid Build Coastguard Worker             blit.src.format = srcStencilRb->surface->format;
621*61046927SAndroid Build Coastguard Worker 
622*61046927SAndroid Build Coastguard Worker             ctx->pipe->blit(ctx->pipe, &blit);
623*61046927SAndroid Build Coastguard Worker          }
624*61046927SAndroid Build Coastguard Worker       }
625*61046927SAndroid Build Coastguard Worker    }
626*61046927SAndroid Build Coastguard Worker }
627*61046927SAndroid Build Coastguard Worker 
628*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
blit_framebuffer(struct gl_context * ctx,struct gl_framebuffer * readFb,struct gl_framebuffer * drawFb,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter,bool no_error,const char * func)629*61046927SAndroid Build Coastguard Worker blit_framebuffer(struct gl_context *ctx,
630*61046927SAndroid Build Coastguard Worker                  struct gl_framebuffer *readFb, struct gl_framebuffer *drawFb,
631*61046927SAndroid Build Coastguard Worker                  GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
632*61046927SAndroid Build Coastguard Worker                  GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
633*61046927SAndroid Build Coastguard Worker                  GLbitfield mask, GLenum filter, bool no_error, const char *func)
634*61046927SAndroid Build Coastguard Worker {
635*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, 0, 0);
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker    if (!readFb || !drawFb) {
638*61046927SAndroid Build Coastguard Worker       /* This will normally never happen but someday we may want to
639*61046927SAndroid Build Coastguard Worker        * support MakeCurrent() with no drawables.
640*61046927SAndroid Build Coastguard Worker        */
641*61046927SAndroid Build Coastguard Worker       return;
642*61046927SAndroid Build Coastguard Worker    }
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker    /* Update completeness status of readFb and drawFb. */
645*61046927SAndroid Build Coastguard Worker    _mesa_update_framebuffer(ctx, readFb, drawFb);
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker    /* Make sure drawFb has an initialized bounding box. */
648*61046927SAndroid Build Coastguard Worker    _mesa_update_draw_buffer_bounds(ctx, drawFb);
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker    if (!no_error) {
651*61046927SAndroid Build Coastguard Worker       const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
652*61046927SAndroid Build Coastguard Worker                                         GL_DEPTH_BUFFER_BIT |
653*61046927SAndroid Build Coastguard Worker                                         GL_STENCIL_BUFFER_BIT);
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker       /* check for complete framebuffers */
656*61046927SAndroid Build Coastguard Worker       if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
657*61046927SAndroid Build Coastguard Worker           readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
658*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
659*61046927SAndroid Build Coastguard Worker                      "%s(incomplete draw/read buffers)", func);
660*61046927SAndroid Build Coastguard Worker          return;
661*61046927SAndroid Build Coastguard Worker       }
662*61046927SAndroid Build Coastguard Worker 
663*61046927SAndroid Build Coastguard Worker       if (!is_valid_blit_filter(ctx, filter)) {
664*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func,
665*61046927SAndroid Build Coastguard Worker                      _mesa_enum_to_string(filter));
666*61046927SAndroid Build Coastguard Worker          return;
667*61046927SAndroid Build Coastguard Worker       }
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker       if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
670*61046927SAndroid Build Coastguard Worker            filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
671*61046927SAndroid Build Coastguard Worker            (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
672*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func,
673*61046927SAndroid Build Coastguard Worker                      _mesa_enum_to_string(filter));
674*61046927SAndroid Build Coastguard Worker          return;
675*61046927SAndroid Build Coastguard Worker       }
676*61046927SAndroid Build Coastguard Worker 
677*61046927SAndroid Build Coastguard Worker       if (mask & ~legalMaskBits) {
678*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func);
679*61046927SAndroid Build Coastguard Worker          return;
680*61046927SAndroid Build Coastguard Worker       }
681*61046927SAndroid Build Coastguard Worker 
682*61046927SAndroid Build Coastguard Worker       /* depth/stencil must be blitted with nearest filtering */
683*61046927SAndroid Build Coastguard Worker       if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
684*61046927SAndroid Build Coastguard Worker            && filter != GL_NEAREST) {
685*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
686*61046927SAndroid Build Coastguard Worker                 "%s(depth/stencil requires GL_NEAREST filter)", func);
687*61046927SAndroid Build Coastguard Worker          return;
688*61046927SAndroid Build Coastguard Worker       }
689*61046927SAndroid Build Coastguard Worker 
690*61046927SAndroid Build Coastguard Worker       if (_mesa_is_gles3(ctx)) {
691*61046927SAndroid Build Coastguard Worker          /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
692*61046927SAndroid Build Coastguard Worker           * 3.0.1 spec says:
693*61046927SAndroid Build Coastguard Worker           *
694*61046927SAndroid Build Coastguard Worker           *     "If SAMPLE_BUFFERS for the draw framebuffer is greater than
695*61046927SAndroid Build Coastguard Worker           *     zero, an INVALID_OPERATION error is generated."
696*61046927SAndroid Build Coastguard Worker           */
697*61046927SAndroid Build Coastguard Worker          if (drawFb->Visual.samples > 0) {
698*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, GL_INVALID_OPERATION,
699*61046927SAndroid Build Coastguard Worker                         "%s(destination samples must be 0)", func);
700*61046927SAndroid Build Coastguard Worker             return;
701*61046927SAndroid Build Coastguard Worker          }
702*61046927SAndroid Build Coastguard Worker 
703*61046927SAndroid Build Coastguard Worker          /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
704*61046927SAndroid Build Coastguard Worker           * 3.0.1 spec says:
705*61046927SAndroid Build Coastguard Worker           *
706*61046927SAndroid Build Coastguard Worker           *     "If SAMPLE_BUFFERS for the read framebuffer is greater than
707*61046927SAndroid Build Coastguard Worker           *     zero, no copy is performed and an INVALID_OPERATION error is
708*61046927SAndroid Build Coastguard Worker           *     generated if the formats of the read and draw framebuffers are
709*61046927SAndroid Build Coastguard Worker           *     not identical or if the source and destination rectangles are
710*61046927SAndroid Build Coastguard Worker           *     not defined with the same (X0, Y0) and (X1, Y1) bounds."
711*61046927SAndroid Build Coastguard Worker           *
712*61046927SAndroid Build Coastguard Worker           * The format check was made above because desktop OpenGL has the same
713*61046927SAndroid Build Coastguard Worker           * requirement.
714*61046927SAndroid Build Coastguard Worker           */
715*61046927SAndroid Build Coastguard Worker          if (readFb->Visual.samples > 0
716*61046927SAndroid Build Coastguard Worker              && (srcX0 != dstX0 || srcY0 != dstY0
717*61046927SAndroid Build Coastguard Worker                  || srcX1 != dstX1 || srcY1 != dstY1)) {
718*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, GL_INVALID_OPERATION,
719*61046927SAndroid Build Coastguard Worker                         "%s(bad src/dst multisample region)", func);
720*61046927SAndroid Build Coastguard Worker             return;
721*61046927SAndroid Build Coastguard Worker          }
722*61046927SAndroid Build Coastguard Worker       } else {
723*61046927SAndroid Build Coastguard Worker          if (readFb->Visual.samples > 0 &&
724*61046927SAndroid Build Coastguard Worker              drawFb->Visual.samples > 0 &&
725*61046927SAndroid Build Coastguard Worker              readFb->Visual.samples != drawFb->Visual.samples) {
726*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, GL_INVALID_OPERATION,
727*61046927SAndroid Build Coastguard Worker                         "%s(mismatched samples)", func);
728*61046927SAndroid Build Coastguard Worker             return;
729*61046927SAndroid Build Coastguard Worker          }
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker          /* extra checks for multisample copies... */
732*61046927SAndroid Build Coastguard Worker          if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
733*61046927SAndroid Build Coastguard Worker              (filter == GL_NEAREST || filter == GL_LINEAR)) {
734*61046927SAndroid Build Coastguard Worker             /* src and dest region sizes must be the same */
735*61046927SAndroid Build Coastguard Worker             if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
736*61046927SAndroid Build Coastguard Worker                 abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
737*61046927SAndroid Build Coastguard Worker                _mesa_error(ctx, GL_INVALID_OPERATION,
738*61046927SAndroid Build Coastguard Worker                            "%s(bad src/dst multisample region sizes)", func);
739*61046927SAndroid Build Coastguard Worker                return;
740*61046927SAndroid Build Coastguard Worker             }
741*61046927SAndroid Build Coastguard Worker          }
742*61046927SAndroid Build Coastguard Worker       }
743*61046927SAndroid Build Coastguard Worker    }
744*61046927SAndroid Build Coastguard Worker 
745*61046927SAndroid Build Coastguard Worker    /* get color read/draw renderbuffers */
746*61046927SAndroid Build Coastguard Worker    if (mask & GL_COLOR_BUFFER_BIT) {
747*61046927SAndroid Build Coastguard Worker       const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
748*61046927SAndroid Build Coastguard Worker       const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
749*61046927SAndroid Build Coastguard Worker 
750*61046927SAndroid Build Coastguard Worker       /* From the EXT_framebuffer_object spec:
751*61046927SAndroid Build Coastguard Worker        *
752*61046927SAndroid Build Coastguard Worker        *     "If a buffer is specified in <mask> and does not exist in both
753*61046927SAndroid Build Coastguard Worker        *     the read and draw framebuffers, the corresponding bit is silently
754*61046927SAndroid Build Coastguard Worker        *     ignored."
755*61046927SAndroid Build Coastguard Worker        */
756*61046927SAndroid Build Coastguard Worker       if (!colorReadRb || numColorDrawBuffers == 0) {
757*61046927SAndroid Build Coastguard Worker          mask &= ~GL_COLOR_BUFFER_BIT;
758*61046927SAndroid Build Coastguard Worker       } else if (!no_error) {
759*61046927SAndroid Build Coastguard Worker          if (!validate_color_buffer(ctx, readFb, drawFb, filter, func))
760*61046927SAndroid Build Coastguard Worker             return;
761*61046927SAndroid Build Coastguard Worker       }
762*61046927SAndroid Build Coastguard Worker    }
763*61046927SAndroid Build Coastguard Worker 
764*61046927SAndroid Build Coastguard Worker    if (mask & GL_STENCIL_BUFFER_BIT) {
765*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *readRb =
766*61046927SAndroid Build Coastguard Worker          readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
767*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *drawRb =
768*61046927SAndroid Build Coastguard Worker          drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker       /* From the EXT_framebuffer_object spec:
771*61046927SAndroid Build Coastguard Worker        *
772*61046927SAndroid Build Coastguard Worker        *     "If a buffer is specified in <mask> and does not exist in both
773*61046927SAndroid Build Coastguard Worker        *     the read and draw framebuffers, the corresponding bit is silently
774*61046927SAndroid Build Coastguard Worker        *     ignored."
775*61046927SAndroid Build Coastguard Worker        */
776*61046927SAndroid Build Coastguard Worker       if ((readRb == NULL) || (drawRb == NULL)) {
777*61046927SAndroid Build Coastguard Worker          mask &= ~GL_STENCIL_BUFFER_BIT;
778*61046927SAndroid Build Coastguard Worker       } else if (!no_error) {
779*61046927SAndroid Build Coastguard Worker          if (!validate_stencil_buffer(ctx, readFb, drawFb, func))
780*61046927SAndroid Build Coastguard Worker             return;
781*61046927SAndroid Build Coastguard Worker       }
782*61046927SAndroid Build Coastguard Worker    }
783*61046927SAndroid Build Coastguard Worker 
784*61046927SAndroid Build Coastguard Worker    if (mask & GL_DEPTH_BUFFER_BIT) {
785*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *readRb =
786*61046927SAndroid Build Coastguard Worker          readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
787*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *drawRb =
788*61046927SAndroid Build Coastguard Worker          drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
789*61046927SAndroid Build Coastguard Worker 
790*61046927SAndroid Build Coastguard Worker       /* From the EXT_framebuffer_object spec:
791*61046927SAndroid Build Coastguard Worker        *
792*61046927SAndroid Build Coastguard Worker        *     "If a buffer is specified in <mask> and does not exist in both
793*61046927SAndroid Build Coastguard Worker        *     the read and draw framebuffers, the corresponding bit is silently
794*61046927SAndroid Build Coastguard Worker        *     ignored."
795*61046927SAndroid Build Coastguard Worker        */
796*61046927SAndroid Build Coastguard Worker       if ((readRb == NULL) || (drawRb == NULL)) {
797*61046927SAndroid Build Coastguard Worker          mask &= ~GL_DEPTH_BUFFER_BIT;
798*61046927SAndroid Build Coastguard Worker       } else if (!no_error) {
799*61046927SAndroid Build Coastguard Worker          if (!validate_depth_buffer(ctx, readFb, drawFb, func))
800*61046927SAndroid Build Coastguard Worker             return;
801*61046927SAndroid Build Coastguard Worker       }
802*61046927SAndroid Build Coastguard Worker    }
803*61046927SAndroid Build Coastguard Worker 
804*61046927SAndroid Build Coastguard Worker    /* Debug code */
805*61046927SAndroid Build Coastguard Worker    if (DEBUG_BLIT) {
806*61046927SAndroid Build Coastguard Worker       const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
807*61046927SAndroid Build Coastguard Worker       const struct gl_renderbuffer *colorDrawRb = NULL;
808*61046927SAndroid Build Coastguard Worker       GLuint i = 0;
809*61046927SAndroid Build Coastguard Worker 
810*61046927SAndroid Build Coastguard Worker       printf("%s(%d, %d, %d, %d,  %d, %d, %d, %d,"
811*61046927SAndroid Build Coastguard Worker              " 0x%x, 0x%x)\n", func,
812*61046927SAndroid Build Coastguard Worker              srcX0, srcY0, srcX1, srcY1,
813*61046927SAndroid Build Coastguard Worker              dstX0, dstY0, dstX1, dstY1,
814*61046927SAndroid Build Coastguard Worker              mask, filter);
815*61046927SAndroid Build Coastguard Worker 
816*61046927SAndroid Build Coastguard Worker       if (colorReadRb) {
817*61046927SAndroid Build Coastguard Worker          const struct gl_renderbuffer_attachment *att;
818*61046927SAndroid Build Coastguard Worker 
819*61046927SAndroid Build Coastguard Worker          att = find_attachment(readFb, colorReadRb);
820*61046927SAndroid Build Coastguard Worker          printf("  Src FBO %u  RB %u (%dx%d)  ",
821*61046927SAndroid Build Coastguard Worker                 readFb->Name, colorReadRb->Name,
822*61046927SAndroid Build Coastguard Worker                 colorReadRb->Width, colorReadRb->Height);
823*61046927SAndroid Build Coastguard Worker          if (att && att->Texture) {
824*61046927SAndroid Build Coastguard Worker             printf("Tex %u  tgt 0x%x  level %u  face %u",
825*61046927SAndroid Build Coastguard Worker                    att->Texture->Name,
826*61046927SAndroid Build Coastguard Worker                    att->Texture->Target,
827*61046927SAndroid Build Coastguard Worker                    att->TextureLevel,
828*61046927SAndroid Build Coastguard Worker                    att->CubeMapFace);
829*61046927SAndroid Build Coastguard Worker          }
830*61046927SAndroid Build Coastguard Worker          printf("\n");
831*61046927SAndroid Build Coastguard Worker 
832*61046927SAndroid Build Coastguard Worker          /* Print all active color render buffers */
833*61046927SAndroid Build Coastguard Worker          for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
834*61046927SAndroid Build Coastguard Worker             colorDrawRb = drawFb->_ColorDrawBuffers[i];
835*61046927SAndroid Build Coastguard Worker             if (!colorDrawRb)
836*61046927SAndroid Build Coastguard Worker                continue;
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker             att = find_attachment(drawFb, colorDrawRb);
839*61046927SAndroid Build Coastguard Worker             printf("  Dst FBO %u  RB %u (%dx%d)  ",
840*61046927SAndroid Build Coastguard Worker                    drawFb->Name, colorDrawRb->Name,
841*61046927SAndroid Build Coastguard Worker                    colorDrawRb->Width, colorDrawRb->Height);
842*61046927SAndroid Build Coastguard Worker             if (att && att->Texture) {
843*61046927SAndroid Build Coastguard Worker                printf("Tex %u  tgt 0x%x  level %u  face %u",
844*61046927SAndroid Build Coastguard Worker                       att->Texture->Name,
845*61046927SAndroid Build Coastguard Worker                       att->Texture->Target,
846*61046927SAndroid Build Coastguard Worker                       att->TextureLevel,
847*61046927SAndroid Build Coastguard Worker                       att->CubeMapFace);
848*61046927SAndroid Build Coastguard Worker             }
849*61046927SAndroid Build Coastguard Worker             printf("\n");
850*61046927SAndroid Build Coastguard Worker          }
851*61046927SAndroid Build Coastguard Worker       }
852*61046927SAndroid Build Coastguard Worker    }
853*61046927SAndroid Build Coastguard Worker 
854*61046927SAndroid Build Coastguard Worker    if (!mask ||
855*61046927SAndroid Build Coastguard Worker        (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
856*61046927SAndroid Build Coastguard Worker        (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
857*61046927SAndroid Build Coastguard Worker       return;
858*61046927SAndroid Build Coastguard Worker    }
859*61046927SAndroid Build Coastguard Worker 
860*61046927SAndroid Build Coastguard Worker    do_blit_framebuffer(ctx, readFb, drawFb,
861*61046927SAndroid Build Coastguard Worker                        srcX0, srcY0, srcX1, srcY1,
862*61046927SAndroid Build Coastguard Worker                        dstX0, dstY0, dstX1, dstY1,
863*61046927SAndroid Build Coastguard Worker                        mask, filter);
864*61046927SAndroid Build Coastguard Worker }
865*61046927SAndroid Build Coastguard Worker 
866*61046927SAndroid Build Coastguard Worker 
867*61046927SAndroid Build Coastguard Worker static void
blit_framebuffer_err(struct gl_context * ctx,struct gl_framebuffer * readFb,struct gl_framebuffer * drawFb,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter,const char * func)868*61046927SAndroid Build Coastguard Worker blit_framebuffer_err(struct gl_context *ctx,
869*61046927SAndroid Build Coastguard Worker                      struct gl_framebuffer *readFb,
870*61046927SAndroid Build Coastguard Worker                      struct gl_framebuffer *drawFb,
871*61046927SAndroid Build Coastguard Worker                      GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
872*61046927SAndroid Build Coastguard Worker                      GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
873*61046927SAndroid Build Coastguard Worker                      GLbitfield mask, GLenum filter, const char *func)
874*61046927SAndroid Build Coastguard Worker {
875*61046927SAndroid Build Coastguard Worker    /* We are wrapping the err variant of the always inlined
876*61046927SAndroid Build Coastguard Worker     * blit_framebuffer() to avoid inlining it in every caller.
877*61046927SAndroid Build Coastguard Worker     */
878*61046927SAndroid Build Coastguard Worker    blit_framebuffer(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
879*61046927SAndroid Build Coastguard Worker                     dstX0, dstY0, dstX1, dstY1, mask, filter, false, func);
880*61046927SAndroid Build Coastguard Worker }
881*61046927SAndroid Build Coastguard Worker 
882*61046927SAndroid Build Coastguard Worker 
883*61046927SAndroid Build Coastguard Worker /**
884*61046927SAndroid Build Coastguard Worker  * Blit rectangular region, optionally from one framebuffer to another.
885*61046927SAndroid Build Coastguard Worker  *
886*61046927SAndroid Build Coastguard Worker  * Note, if the src buffer is multisampled and the dest is not, this is
887*61046927SAndroid Build Coastguard Worker  * when the samples must be resolved to a single color.
888*61046927SAndroid Build Coastguard Worker  */
889*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_BlitFramebuffer_no_error(GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)890*61046927SAndroid Build Coastguard Worker _mesa_BlitFramebuffer_no_error(GLint srcX0, GLint srcY0, GLint srcX1,
891*61046927SAndroid Build Coastguard Worker                                GLint srcY1, GLint dstX0, GLint dstY0,
892*61046927SAndroid Build Coastguard Worker                                GLint dstX1, GLint dstY1,
893*61046927SAndroid Build Coastguard Worker                                GLbitfield mask, GLenum filter)
894*61046927SAndroid Build Coastguard Worker {
895*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
896*61046927SAndroid Build Coastguard Worker 
897*61046927SAndroid Build Coastguard Worker    blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
898*61046927SAndroid Build Coastguard Worker                     srcX0, srcY0, srcX1, srcY1,
899*61046927SAndroid Build Coastguard Worker                     dstX0, dstY0, dstX1, dstY1,
900*61046927SAndroid Build Coastguard Worker                     mask, filter, true, "glBlitFramebuffer");
901*61046927SAndroid Build Coastguard Worker }
902*61046927SAndroid Build Coastguard Worker 
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_BlitFramebuffer(GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)905*61046927SAndroid Build Coastguard Worker _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
906*61046927SAndroid Build Coastguard Worker                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
907*61046927SAndroid Build Coastguard Worker                       GLbitfield mask, GLenum filter)
908*61046927SAndroid Build Coastguard Worker {
909*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
910*61046927SAndroid Build Coastguard Worker 
911*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
912*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx,
913*61046927SAndroid Build Coastguard Worker                   "glBlitFramebuffer(%d, %d, %d, %d, "
914*61046927SAndroid Build Coastguard Worker                   " %d, %d, %d, %d, 0x%x, %s)\n",
915*61046927SAndroid Build Coastguard Worker                   srcX0, srcY0, srcX1, srcY1,
916*61046927SAndroid Build Coastguard Worker                   dstX0, dstY0, dstX1, dstY1,
917*61046927SAndroid Build Coastguard Worker                   mask, _mesa_enum_to_string(filter));
918*61046927SAndroid Build Coastguard Worker 
919*61046927SAndroid Build Coastguard Worker    blit_framebuffer_err(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
920*61046927SAndroid Build Coastguard Worker                         srcX0, srcY0, srcX1, srcY1,
921*61046927SAndroid Build Coastguard Worker                         dstX0, dstY0, dstX1, dstY1,
922*61046927SAndroid Build Coastguard Worker                         mask, filter, "glBlitFramebuffer");
923*61046927SAndroid Build Coastguard Worker }
924*61046927SAndroid Build Coastguard Worker 
925*61046927SAndroid Build Coastguard Worker 
926*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
blit_named_framebuffer(struct gl_context * ctx,GLuint readFramebuffer,GLuint drawFramebuffer,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter,bool no_error)927*61046927SAndroid Build Coastguard Worker blit_named_framebuffer(struct gl_context *ctx,
928*61046927SAndroid Build Coastguard Worker                        GLuint readFramebuffer, GLuint drawFramebuffer,
929*61046927SAndroid Build Coastguard Worker                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
930*61046927SAndroid Build Coastguard Worker                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
931*61046927SAndroid Build Coastguard Worker                        GLbitfield mask, GLenum filter, bool no_error)
932*61046927SAndroid Build Coastguard Worker {
933*61046927SAndroid Build Coastguard Worker    struct gl_framebuffer *readFb, *drawFb;
934*61046927SAndroid Build Coastguard Worker 
935*61046927SAndroid Build Coastguard Worker    /*
936*61046927SAndroid Build Coastguard Worker     * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014,
937*61046927SAndroid Build Coastguard Worker     * Section 18.3 Copying Pixels):
938*61046927SAndroid Build Coastguard Worker     *   "... if readFramebuffer or drawFramebuffer is zero (for
939*61046927SAndroid Build Coastguard Worker     *   BlitNamedFramebuffer), then the default read or draw framebuffer is
940*61046927SAndroid Build Coastguard Worker     *   used as the corresponding source or destination framebuffer,
941*61046927SAndroid Build Coastguard Worker     *   respectively."
942*61046927SAndroid Build Coastguard Worker     */
943*61046927SAndroid Build Coastguard Worker    if (readFramebuffer) {
944*61046927SAndroid Build Coastguard Worker       if (no_error) {
945*61046927SAndroid Build Coastguard Worker          readFb = _mesa_lookup_framebuffer(ctx, readFramebuffer);
946*61046927SAndroid Build Coastguard Worker       } else {
947*61046927SAndroid Build Coastguard Worker          readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer,
948*61046927SAndroid Build Coastguard Worker                                                "glBlitNamedFramebuffer");
949*61046927SAndroid Build Coastguard Worker          if (!readFb)
950*61046927SAndroid Build Coastguard Worker             return;
951*61046927SAndroid Build Coastguard Worker       }
952*61046927SAndroid Build Coastguard Worker    } else {
953*61046927SAndroid Build Coastguard Worker       readFb = ctx->WinSysReadBuffer;
954*61046927SAndroid Build Coastguard Worker    }
955*61046927SAndroid Build Coastguard Worker 
956*61046927SAndroid Build Coastguard Worker    if (drawFramebuffer) {
957*61046927SAndroid Build Coastguard Worker       if (no_error) {
958*61046927SAndroid Build Coastguard Worker          drawFb = _mesa_lookup_framebuffer(ctx, drawFramebuffer);
959*61046927SAndroid Build Coastguard Worker       } else {
960*61046927SAndroid Build Coastguard Worker          drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer,
961*61046927SAndroid Build Coastguard Worker                                                "glBlitNamedFramebuffer");
962*61046927SAndroid Build Coastguard Worker          if (!drawFb)
963*61046927SAndroid Build Coastguard Worker             return;
964*61046927SAndroid Build Coastguard Worker       }
965*61046927SAndroid Build Coastguard Worker    } else {
966*61046927SAndroid Build Coastguard Worker       drawFb = ctx->WinSysDrawBuffer;
967*61046927SAndroid Build Coastguard Worker    }
968*61046927SAndroid Build Coastguard Worker 
969*61046927SAndroid Build Coastguard Worker    blit_framebuffer(ctx, readFb, drawFb,
970*61046927SAndroid Build Coastguard Worker                     srcX0, srcY0, srcX1, srcY1,
971*61046927SAndroid Build Coastguard Worker                     dstX0, dstY0, dstX1, dstY1,
972*61046927SAndroid Build Coastguard Worker                     mask, filter, no_error, "glBlitNamedFramebuffer");
973*61046927SAndroid Build Coastguard Worker }
974*61046927SAndroid Build Coastguard Worker 
975*61046927SAndroid Build Coastguard Worker 
976*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_BlitNamedFramebuffer_no_error(GLuint readFramebuffer,GLuint drawFramebuffer,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)977*61046927SAndroid Build Coastguard Worker _mesa_BlitNamedFramebuffer_no_error(GLuint readFramebuffer,
978*61046927SAndroid Build Coastguard Worker                                     GLuint drawFramebuffer,
979*61046927SAndroid Build Coastguard Worker                                     GLint srcX0, GLint srcY0,
980*61046927SAndroid Build Coastguard Worker                                     GLint srcX1, GLint srcY1,
981*61046927SAndroid Build Coastguard Worker                                     GLint dstX0, GLint dstY0,
982*61046927SAndroid Build Coastguard Worker                                     GLint dstX1, GLint dstY1,
983*61046927SAndroid Build Coastguard Worker                                     GLbitfield mask, GLenum filter)
984*61046927SAndroid Build Coastguard Worker {
985*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
986*61046927SAndroid Build Coastguard Worker 
987*61046927SAndroid Build Coastguard Worker    blit_named_framebuffer(ctx, readFramebuffer, drawFramebuffer,
988*61046927SAndroid Build Coastguard Worker                           srcX0, srcY0, srcX1, srcY1,
989*61046927SAndroid Build Coastguard Worker                           dstX0, dstY0, dstX1, dstY1,
990*61046927SAndroid Build Coastguard Worker                           mask, filter, true);
991*61046927SAndroid Build Coastguard Worker }
992*61046927SAndroid Build Coastguard Worker 
993*61046927SAndroid Build Coastguard Worker 
994*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_BlitNamedFramebuffer(GLuint readFramebuffer,GLuint drawFramebuffer,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)995*61046927SAndroid Build Coastguard Worker _mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
996*61046927SAndroid Build Coastguard Worker                            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
997*61046927SAndroid Build Coastguard Worker                            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
998*61046927SAndroid Build Coastguard Worker                            GLbitfield mask, GLenum filter)
999*61046927SAndroid Build Coastguard Worker {
1000*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1001*61046927SAndroid Build Coastguard Worker 
1002*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
1003*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx,
1004*61046927SAndroid Build Coastguard Worker                   "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, "
1005*61046927SAndroid Build Coastguard Worker                   " %d, %d, %d, %d, 0x%x, %s)\n",
1006*61046927SAndroid Build Coastguard Worker                   readFramebuffer, drawFramebuffer,
1007*61046927SAndroid Build Coastguard Worker                   srcX0, srcY0, srcX1, srcY1,
1008*61046927SAndroid Build Coastguard Worker                   dstX0, dstY0, dstX1, dstY1,
1009*61046927SAndroid Build Coastguard Worker                   mask, _mesa_enum_to_string(filter));
1010*61046927SAndroid Build Coastguard Worker 
1011*61046927SAndroid Build Coastguard Worker    blit_named_framebuffer(ctx, readFramebuffer, drawFramebuffer,
1012*61046927SAndroid Build Coastguard Worker                           srcX0, srcY0, srcX1, srcY1,
1013*61046927SAndroid Build Coastguard Worker                           dstX0, dstY0, dstX1, dstY1,
1014*61046927SAndroid Build Coastguard Worker                           mask, filter, false);
1015*61046927SAndroid Build Coastguard Worker }
1016