xref: /aosp_15_r20/external/mesa3d/src/mesa/main/pbo.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) 2009-2011  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 /**
28*61046927SAndroid Build Coastguard Worker  * \file pbo.c
29*61046927SAndroid Build Coastguard Worker  * \brief Functions related to Pixel Buffer Objects.
30*61046927SAndroid Build Coastguard Worker  */
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker #include "errors.h"
35*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
36*61046927SAndroid Build Coastguard Worker #include "bufferobj.h"
37*61046927SAndroid Build Coastguard Worker #include "glformats.h"
38*61046927SAndroid Build Coastguard Worker #include "image.h"
39*61046927SAndroid Build Coastguard Worker #include "mtypes.h"
40*61046927SAndroid Build Coastguard Worker #include "macros.h"
41*61046927SAndroid Build Coastguard Worker #include "pbo.h"
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker /**
44*61046927SAndroid Build Coastguard Worker  * When we're about to read pixel data out of a PBO (via glDrawPixels,
45*61046927SAndroid Build Coastguard Worker  * glTexImage, etc) or write data into a PBO (via glReadPixels,
46*61046927SAndroid Build Coastguard Worker  * glGetTexImage, etc) we call this function to check that we're not
47*61046927SAndroid Build Coastguard Worker  * going to read/write out of bounds.
48*61046927SAndroid Build Coastguard Worker  *
49*61046927SAndroid Build Coastguard Worker  * XXX This would also be a convenient time to check that the PBO isn't
50*61046927SAndroid Build Coastguard Worker  * currently mapped.  Whoever calls this function should check for that.
51*61046927SAndroid Build Coastguard Worker  * Remember, we can't use a PBO when it's mapped!
52*61046927SAndroid Build Coastguard Worker  *
53*61046927SAndroid Build Coastguard Worker  * If we're not using a PBO, this is a no-op.
54*61046927SAndroid Build Coastguard Worker  *
55*61046927SAndroid Build Coastguard Worker  * \param width  width of image to read/write
56*61046927SAndroid Build Coastguard Worker  * \param height  height of image to read/write
57*61046927SAndroid Build Coastguard Worker  * \param depth  depth of image to read/write
58*61046927SAndroid Build Coastguard Worker  * \param format  format of image to read/write
59*61046927SAndroid Build Coastguard Worker  * \param type  datatype of image to read/write
60*61046927SAndroid Build Coastguard Worker  * \param clientMemSize  the maximum number of bytes to read/write
61*61046927SAndroid Build Coastguard Worker  * \param ptr  the user-provided pointer/offset
62*61046927SAndroid Build Coastguard Worker  * \return GL_TRUE if the buffer access is OK, GL_FALSE if the access would
63*61046927SAndroid Build Coastguard Worker  *         go out of bounds.
64*61046927SAndroid Build Coastguard Worker  */
65*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_validate_pbo_access(GLuint dimensions,const struct gl_pixelstore_attrib * pack,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei clientMemSize,const GLvoid * ptr)66*61046927SAndroid Build Coastguard Worker _mesa_validate_pbo_access(GLuint dimensions,
67*61046927SAndroid Build Coastguard Worker                           const struct gl_pixelstore_attrib *pack,
68*61046927SAndroid Build Coastguard Worker                           GLsizei width, GLsizei height, GLsizei depth,
69*61046927SAndroid Build Coastguard Worker                           GLenum format, GLenum type, GLsizei clientMemSize,
70*61046927SAndroid Build Coastguard Worker                           const GLvoid *ptr)
71*61046927SAndroid Build Coastguard Worker {
72*61046927SAndroid Build Coastguard Worker    /* unsigned, to detect overflow/wrap-around */
73*61046927SAndroid Build Coastguard Worker    uintptr_t start, end, offset, size;
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    /* If no PBO is bound, 'ptr' is a pointer to client memory containing
76*61046927SAndroid Build Coastguard Worker       'clientMemSize' bytes.
77*61046927SAndroid Build Coastguard Worker       If a PBO is bound, 'ptr' is an offset into the bound PBO.
78*61046927SAndroid Build Coastguard Worker       In that case 'clientMemSize' is ignored: we just use the PBO's size.
79*61046927SAndroid Build Coastguard Worker     */
80*61046927SAndroid Build Coastguard Worker    if (!pack->BufferObj) {
81*61046927SAndroid Build Coastguard Worker       offset = 0;
82*61046927SAndroid Build Coastguard Worker       size = (clientMemSize == INT_MAX) ? UINTPTR_MAX : clientMemSize;
83*61046927SAndroid Build Coastguard Worker    } else {
84*61046927SAndroid Build Coastguard Worker       offset = (uintptr_t)ptr;
85*61046927SAndroid Build Coastguard Worker       size = pack->BufferObj->Size;
86*61046927SAndroid Build Coastguard Worker       /* The ARB_pixel_buffer_object spec says:
87*61046927SAndroid Build Coastguard Worker        *    "INVALID_OPERATION is generated by ColorTable, ColorSubTable,
88*61046927SAndroid Build Coastguard Worker        *    ConvolutionFilter2D, ConvolutionFilter1D, SeparableFilter2D,
89*61046927SAndroid Build Coastguard Worker        *    TexImage1D, TexImage2D, TexImage3D, TexSubImage1D,
90*61046927SAndroid Build Coastguard Worker        *    TexSubImage2D, TexSubImage3D, and DrawPixels if the current
91*61046927SAndroid Build Coastguard Worker        *    PIXEL_UNPACK_BUFFER_BINDING_ARB value is non-zero and the data
92*61046927SAndroid Build Coastguard Worker        *    parameter is not evenly divisible into the number of basic machine
93*61046927SAndroid Build Coastguard Worker        *    units needed to store in memory a datum indicated by the type
94*61046927SAndroid Build Coastguard Worker        *    parameter."
95*61046927SAndroid Build Coastguard Worker        */
96*61046927SAndroid Build Coastguard Worker       if (type != GL_BITMAP &&
97*61046927SAndroid Build Coastguard Worker           (offset % _mesa_sizeof_packed_type(type)))
98*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
99*61046927SAndroid Build Coastguard Worker    }
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker    if (size == 0)
102*61046927SAndroid Build Coastguard Worker       /* no buffer! */
103*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker    /* If the size of the image is zero then no pixels are accessed so we
106*61046927SAndroid Build Coastguard Worker     * don't need to check anything else.
107*61046927SAndroid Build Coastguard Worker     */
108*61046927SAndroid Build Coastguard Worker    if (width == 0 || height == 0 || depth == 0)
109*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    /* get the offset to the first pixel we'll read/write */
112*61046927SAndroid Build Coastguard Worker    start = _mesa_image_offset(dimensions, pack, width, height,
113*61046927SAndroid Build Coastguard Worker                               format, type, 0, 0, 0);
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker    /* get the offset to just past the last pixel we'll read/write */
116*61046927SAndroid Build Coastguard Worker    end =  _mesa_image_offset(dimensions, pack, width, height,
117*61046927SAndroid Build Coastguard Worker                              format, type, depth-1, height-1, width);
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker    start += offset;
120*61046927SAndroid Build Coastguard Worker    end += offset;
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    if (start > size) {
123*61046927SAndroid Build Coastguard Worker       /* This will catch negative values / wrap-around */
124*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
125*61046927SAndroid Build Coastguard Worker    }
126*61046927SAndroid Build Coastguard Worker    if (end > size) {
127*61046927SAndroid Build Coastguard Worker       /* Image read/write goes beyond end of buffer */
128*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
129*61046927SAndroid Build Coastguard Worker    }
130*61046927SAndroid Build Coastguard Worker 
131*61046927SAndroid Build Coastguard Worker    /* OK! */
132*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
133*61046927SAndroid Build Coastguard Worker }
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker /**
137*61046927SAndroid Build Coastguard Worker  * For commands that read from a PBO (glDrawPixels, glTexImage,
138*61046927SAndroid Build Coastguard Worker  * glPolygonStipple, etc), if we're reading from a PBO, map it read-only
139*61046927SAndroid Build Coastguard Worker  * and return the pointer into the PBO.  If we're not reading from a
140*61046927SAndroid Build Coastguard Worker  * PBO, return \p src as-is.
141*61046927SAndroid Build Coastguard Worker  * If non-null return, must call _mesa_unmap_pbo_source() when done.
142*61046927SAndroid Build Coastguard Worker  *
143*61046927SAndroid Build Coastguard Worker  * \return NULL if error, else pointer to start of data
144*61046927SAndroid Build Coastguard Worker  */
145*61046927SAndroid Build Coastguard Worker const GLvoid *
_mesa_map_pbo_source(struct gl_context * ctx,const struct gl_pixelstore_attrib * unpack,const GLvoid * src)146*61046927SAndroid Build Coastguard Worker _mesa_map_pbo_source(struct gl_context *ctx,
147*61046927SAndroid Build Coastguard Worker                      const struct gl_pixelstore_attrib *unpack,
148*61046927SAndroid Build Coastguard Worker                      const GLvoid *src)
149*61046927SAndroid Build Coastguard Worker {
150*61046927SAndroid Build Coastguard Worker    const GLubyte *buf;
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker    if (unpack->BufferObj) {
153*61046927SAndroid Build Coastguard Worker       /* unpack from PBO */
154*61046927SAndroid Build Coastguard Worker       buf = (GLubyte *) _mesa_bufferobj_map_range(ctx, 0,
155*61046927SAndroid Build Coastguard Worker                                                   unpack->BufferObj->Size,
156*61046927SAndroid Build Coastguard Worker                                                   GL_MAP_READ_BIT,
157*61046927SAndroid Build Coastguard Worker                                                   unpack->BufferObj,
158*61046927SAndroid Build Coastguard Worker                                                   MAP_INTERNAL);
159*61046927SAndroid Build Coastguard Worker       if (!buf)
160*61046927SAndroid Build Coastguard Worker          return NULL;
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker       buf = ADD_POINTERS(buf, src);
163*61046927SAndroid Build Coastguard Worker    }
164*61046927SAndroid Build Coastguard Worker    else {
165*61046927SAndroid Build Coastguard Worker       /* unpack from normal memory */
166*61046927SAndroid Build Coastguard Worker       buf = src;
167*61046927SAndroid Build Coastguard Worker    }
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    return buf;
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker /**
173*61046927SAndroid Build Coastguard Worker  * Perform PBO validation for read operations with uncompressed textures.
174*61046927SAndroid Build Coastguard Worker  * If any GL errors are detected, false is returned, otherwise returns true.
175*61046927SAndroid Build Coastguard Worker  * \sa _mesa_validate_pbo_access
176*61046927SAndroid Build Coastguard Worker  */
177*61046927SAndroid Build Coastguard Worker bool
_mesa_validate_pbo_source(struct gl_context * ctx,GLuint dimensions,const struct gl_pixelstore_attrib * unpack,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei clientMemSize,const GLvoid * ptr,const char * where)178*61046927SAndroid Build Coastguard Worker _mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions,
179*61046927SAndroid Build Coastguard Worker                           const struct gl_pixelstore_attrib *unpack,
180*61046927SAndroid Build Coastguard Worker                           GLsizei width, GLsizei height, GLsizei depth,
181*61046927SAndroid Build Coastguard Worker                           GLenum format, GLenum type,
182*61046927SAndroid Build Coastguard Worker                           GLsizei clientMemSize,
183*61046927SAndroid Build Coastguard Worker                           const GLvoid *ptr, const char *where)
184*61046927SAndroid Build Coastguard Worker {
185*61046927SAndroid Build Coastguard Worker    assert(dimensions == 1 || dimensions == 2 || dimensions == 3);
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker    if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
188*61046927SAndroid Build Coastguard Worker                                   format, type, clientMemSize, ptr)) {
189*61046927SAndroid Build Coastguard Worker       if (unpack->BufferObj) {
190*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
191*61046927SAndroid Build Coastguard Worker                      "%s(out of bounds PBO access)",
192*61046927SAndroid Build Coastguard Worker                      where);
193*61046927SAndroid Build Coastguard Worker       } else {
194*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
195*61046927SAndroid Build Coastguard Worker                      "%s(out of bounds access: bufSize (%d) is too small)",
196*61046927SAndroid Build Coastguard Worker                      where, clientMemSize);
197*61046927SAndroid Build Coastguard Worker       }
198*61046927SAndroid Build Coastguard Worker       return false;
199*61046927SAndroid Build Coastguard Worker    }
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker    if (!unpack->BufferObj) {
202*61046927SAndroid Build Coastguard Worker       /* non-PBO access: no further validation to be done */
203*61046927SAndroid Build Coastguard Worker       return true;
204*61046927SAndroid Build Coastguard Worker    }
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker    if (_mesa_check_disallowed_mapping(unpack->BufferObj)) {
207*61046927SAndroid Build Coastguard Worker       /* buffer is already mapped - that's an error */
208*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)",
209*61046927SAndroid Build Coastguard Worker                   where);
210*61046927SAndroid Build Coastguard Worker       return false;
211*61046927SAndroid Build Coastguard Worker    }
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker    return true;
214*61046927SAndroid Build Coastguard Worker }
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker /**
217*61046927SAndroid Build Coastguard Worker  * Perform PBO validation for read operations with compressed textures.
218*61046927SAndroid Build Coastguard Worker  * If any GL errors are detected, false is returned, otherwise returns true.
219*61046927SAndroid Build Coastguard Worker  */
220*61046927SAndroid Build Coastguard Worker bool
_mesa_validate_pbo_source_compressed(struct gl_context * ctx,GLuint dimensions,const struct gl_pixelstore_attrib * unpack,GLsizei imageSize,const GLvoid * pixels,const char * where)221*61046927SAndroid Build Coastguard Worker _mesa_validate_pbo_source_compressed(struct gl_context *ctx, GLuint dimensions,
222*61046927SAndroid Build Coastguard Worker                                      const struct gl_pixelstore_attrib *unpack,
223*61046927SAndroid Build Coastguard Worker                                      GLsizei imageSize, const GLvoid *pixels,
224*61046927SAndroid Build Coastguard Worker                                      const char *where)
225*61046927SAndroid Build Coastguard Worker {
226*61046927SAndroid Build Coastguard Worker    if (!unpack->BufferObj) {
227*61046927SAndroid Build Coastguard Worker       /* not using a PBO */
228*61046927SAndroid Build Coastguard Worker       return true;
229*61046927SAndroid Build Coastguard Worker    }
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    if ((const GLubyte *) pixels + imageSize >
232*61046927SAndroid Build Coastguard Worker        ((const GLubyte *) 0) + unpack->BufferObj->Size) {
233*61046927SAndroid Build Coastguard Worker       /* out of bounds read! */
234*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid PBO access)",
235*61046927SAndroid Build Coastguard Worker                   where);
236*61046927SAndroid Build Coastguard Worker       return false;
237*61046927SAndroid Build Coastguard Worker    }
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    if (_mesa_check_disallowed_mapping(unpack->BufferObj)) {
240*61046927SAndroid Build Coastguard Worker       /* buffer is already mapped - that's an error */
241*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)",
242*61046927SAndroid Build Coastguard Worker                   where);
243*61046927SAndroid Build Coastguard Worker       return false;
244*61046927SAndroid Build Coastguard Worker    }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker    return true;
247*61046927SAndroid Build Coastguard Worker }
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker /**
250*61046927SAndroid Build Coastguard Worker  * Perform PBO-read mapping.
251*61046927SAndroid Build Coastguard Worker  * If any GL errors are detected, they'll be recorded and NULL returned.
252*61046927SAndroid Build Coastguard Worker  * \sa _mesa_validate_pbo_source
253*61046927SAndroid Build Coastguard Worker  * \sa _mesa_map_pbo_source
254*61046927SAndroid Build Coastguard Worker  * A call to this function should have a matching call to
255*61046927SAndroid Build Coastguard Worker  * _mesa_unmap_pbo_source().
256*61046927SAndroid Build Coastguard Worker  */
257*61046927SAndroid Build Coastguard Worker const GLvoid *
_mesa_map_validate_pbo_source(struct gl_context * ctx,GLuint dimensions,const struct gl_pixelstore_attrib * unpack,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei clientMemSize,const GLvoid * ptr,const char * where)258*61046927SAndroid Build Coastguard Worker _mesa_map_validate_pbo_source(struct gl_context *ctx,
259*61046927SAndroid Build Coastguard Worker                               GLuint dimensions,
260*61046927SAndroid Build Coastguard Worker                               const struct gl_pixelstore_attrib *unpack,
261*61046927SAndroid Build Coastguard Worker                               GLsizei width, GLsizei height, GLsizei depth,
262*61046927SAndroid Build Coastguard Worker                               GLenum format, GLenum type,
263*61046927SAndroid Build Coastguard Worker                               GLsizei clientMemSize,
264*61046927SAndroid Build Coastguard Worker                               const GLvoid *ptr, const char *where)
265*61046927SAndroid Build Coastguard Worker {
266*61046927SAndroid Build Coastguard Worker    if (!_mesa_validate_pbo_source(ctx, dimensions, unpack,
267*61046927SAndroid Build Coastguard Worker                                   width, height, depth, format, type,
268*61046927SAndroid Build Coastguard Worker                                   clientMemSize, ptr, where)) {
269*61046927SAndroid Build Coastguard Worker      return NULL;
270*61046927SAndroid Build Coastguard Worker    }
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
273*61046927SAndroid Build Coastguard Worker    return ptr;
274*61046927SAndroid Build Coastguard Worker }
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker 
277*61046927SAndroid Build Coastguard Worker /**
278*61046927SAndroid Build Coastguard Worker  * Counterpart to _mesa_map_pbo_source()
279*61046927SAndroid Build Coastguard Worker  */
280*61046927SAndroid Build Coastguard Worker void
_mesa_unmap_pbo_source(struct gl_context * ctx,const struct gl_pixelstore_attrib * unpack)281*61046927SAndroid Build Coastguard Worker _mesa_unmap_pbo_source(struct gl_context *ctx,
282*61046927SAndroid Build Coastguard Worker                        const struct gl_pixelstore_attrib *unpack)
283*61046927SAndroid Build Coastguard Worker {
284*61046927SAndroid Build Coastguard Worker    assert(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
285*61046927SAndroid Build Coastguard Worker    if (unpack->BufferObj) {
286*61046927SAndroid Build Coastguard Worker       _mesa_bufferobj_unmap(ctx, unpack->BufferObj, MAP_INTERNAL);
287*61046927SAndroid Build Coastguard Worker    }
288*61046927SAndroid Build Coastguard Worker }
289*61046927SAndroid Build Coastguard Worker 
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker /**
292*61046927SAndroid Build Coastguard Worker  * For commands that write to a PBO (glReadPixels, glGetColorTable, etc),
293*61046927SAndroid Build Coastguard Worker  * if we're writing to a PBO, map it write-only and return the pointer
294*61046927SAndroid Build Coastguard Worker  * into the PBO.  If we're not writing to a PBO, return \p dst as-is.
295*61046927SAndroid Build Coastguard Worker  * If non-null return, must call _mesa_unmap_pbo_dest() when done.
296*61046927SAndroid Build Coastguard Worker  *
297*61046927SAndroid Build Coastguard Worker  * \return NULL if error, else pointer to start of data
298*61046927SAndroid Build Coastguard Worker  */
299*61046927SAndroid Build Coastguard Worker void *
_mesa_map_pbo_dest(struct gl_context * ctx,const struct gl_pixelstore_attrib * pack,GLvoid * dest)300*61046927SAndroid Build Coastguard Worker _mesa_map_pbo_dest(struct gl_context *ctx,
301*61046927SAndroid Build Coastguard Worker                    const struct gl_pixelstore_attrib *pack,
302*61046927SAndroid Build Coastguard Worker                    GLvoid *dest)
303*61046927SAndroid Build Coastguard Worker {
304*61046927SAndroid Build Coastguard Worker    void *buf;
305*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker    if (pack->BufferObj) {
307*61046927SAndroid Build Coastguard Worker       /* pack into PBO */
308*61046927SAndroid Build Coastguard Worker       buf = (GLubyte *) _mesa_bufferobj_map_range(ctx, 0,
309*61046927SAndroid Build Coastguard Worker                                                   pack->BufferObj->Size,
310*61046927SAndroid Build Coastguard Worker                                                   GL_MAP_WRITE_BIT,
311*61046927SAndroid Build Coastguard Worker                                                   pack->BufferObj,
312*61046927SAndroid Build Coastguard Worker                                                   MAP_INTERNAL);
313*61046927SAndroid Build Coastguard Worker       if (!buf)
314*61046927SAndroid Build Coastguard Worker          return NULL;
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker       buf = ADD_POINTERS(buf, dest);
317*61046927SAndroid Build Coastguard Worker    }
318*61046927SAndroid Build Coastguard Worker    else {
319*61046927SAndroid Build Coastguard Worker       /* pack to normal memory */
320*61046927SAndroid Build Coastguard Worker       buf = dest;
321*61046927SAndroid Build Coastguard Worker    }
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    return buf;
324*61046927SAndroid Build Coastguard Worker }
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker /**
328*61046927SAndroid Build Coastguard Worker  * Combine PBO-write validation and mapping.
329*61046927SAndroid Build Coastguard Worker  * If any GL errors are detected, they'll be recorded and NULL returned.
330*61046927SAndroid Build Coastguard Worker  * \sa _mesa_validate_pbo_access
331*61046927SAndroid Build Coastguard Worker  * \sa _mesa_map_pbo_dest
332*61046927SAndroid Build Coastguard Worker  * A call to this function should have a matching call to
333*61046927SAndroid Build Coastguard Worker  * _mesa_unmap_pbo_dest().
334*61046927SAndroid Build Coastguard Worker  */
335*61046927SAndroid Build Coastguard Worker GLvoid *
_mesa_map_validate_pbo_dest(struct gl_context * ctx,GLuint dimensions,const struct gl_pixelstore_attrib * unpack,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei clientMemSize,GLvoid * ptr,const char * where)336*61046927SAndroid Build Coastguard Worker _mesa_map_validate_pbo_dest(struct gl_context *ctx,
337*61046927SAndroid Build Coastguard Worker                             GLuint dimensions,
338*61046927SAndroid Build Coastguard Worker                             const struct gl_pixelstore_attrib *unpack,
339*61046927SAndroid Build Coastguard Worker                             GLsizei width, GLsizei height, GLsizei depth,
340*61046927SAndroid Build Coastguard Worker                             GLenum format, GLenum type, GLsizei clientMemSize,
341*61046927SAndroid Build Coastguard Worker                             GLvoid *ptr, const char *where)
342*61046927SAndroid Build Coastguard Worker {
343*61046927SAndroid Build Coastguard Worker    assert(dimensions == 1 || dimensions == 2 || dimensions == 3);
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker    if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
346*61046927SAndroid Build Coastguard Worker                                   format, type, clientMemSize, ptr)) {
347*61046927SAndroid Build Coastguard Worker       if (unpack->BufferObj) {
348*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
349*61046927SAndroid Build Coastguard Worker                      "%s(out of bounds PBO access)", where);
350*61046927SAndroid Build Coastguard Worker       } else {
351*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
352*61046927SAndroid Build Coastguard Worker                      "%s(out of bounds access: bufSize (%d) is too small)",
353*61046927SAndroid Build Coastguard Worker                      where, clientMemSize);
354*61046927SAndroid Build Coastguard Worker       }
355*61046927SAndroid Build Coastguard Worker       return NULL;
356*61046927SAndroid Build Coastguard Worker    }
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker    if (!unpack->BufferObj) {
359*61046927SAndroid Build Coastguard Worker       /* non-PBO access: no further validation to be done */
360*61046927SAndroid Build Coastguard Worker       return ptr;
361*61046927SAndroid Build Coastguard Worker    }
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker    if (_mesa_check_disallowed_mapping(unpack->BufferObj)) {
364*61046927SAndroid Build Coastguard Worker       /* buffer is already mapped - that's an error */
365*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
366*61046927SAndroid Build Coastguard Worker       return NULL;
367*61046927SAndroid Build Coastguard Worker    }
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    ptr = _mesa_map_pbo_dest(ctx, unpack, ptr);
370*61046927SAndroid Build Coastguard Worker    return ptr;
371*61046927SAndroid Build Coastguard Worker }
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker /**
375*61046927SAndroid Build Coastguard Worker  * Counterpart to _mesa_map_pbo_dest()
376*61046927SAndroid Build Coastguard Worker  */
377*61046927SAndroid Build Coastguard Worker void
_mesa_unmap_pbo_dest(struct gl_context * ctx,const struct gl_pixelstore_attrib * pack)378*61046927SAndroid Build Coastguard Worker _mesa_unmap_pbo_dest(struct gl_context *ctx,
379*61046927SAndroid Build Coastguard Worker                      const struct gl_pixelstore_attrib *pack)
380*61046927SAndroid Build Coastguard Worker {
381*61046927SAndroid Build Coastguard Worker    assert(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
382*61046927SAndroid Build Coastguard Worker    if (pack->BufferObj) {
383*61046927SAndroid Build Coastguard Worker       _mesa_bufferobj_unmap(ctx, pack->BufferObj, MAP_INTERNAL);
384*61046927SAndroid Build Coastguard Worker    }
385*61046927SAndroid Build Coastguard Worker }
386*61046927SAndroid Build Coastguard Worker 
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker /**
389*61046927SAndroid Build Coastguard Worker  * Check if an unpack PBO is active prior to fetching a texture image.
390*61046927SAndroid Build Coastguard Worker  * If so, do bounds checking and map the buffer into main memory.
391*61046927SAndroid Build Coastguard Worker  * Any errors detected will be recorded.
392*61046927SAndroid Build Coastguard Worker  * The caller _must_ call _mesa_unmap_teximage_pbo() too!
393*61046927SAndroid Build Coastguard Worker  */
394*61046927SAndroid Build Coastguard Worker const GLvoid *
_mesa_validate_pbo_teximage(struct gl_context * ctx,GLuint dimensions,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const GLvoid * pixels,const struct gl_pixelstore_attrib * unpack,const char * funcName)395*61046927SAndroid Build Coastguard Worker _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
396*61046927SAndroid Build Coastguard Worker 			    GLsizei width, GLsizei height, GLsizei depth,
397*61046927SAndroid Build Coastguard Worker 			    GLenum format, GLenum type, const GLvoid *pixels,
398*61046927SAndroid Build Coastguard Worker 			    const struct gl_pixelstore_attrib *unpack,
399*61046927SAndroid Build Coastguard Worker 			    const char *funcName)
400*61046927SAndroid Build Coastguard Worker {
401*61046927SAndroid Build Coastguard Worker    GLubyte *buf;
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker    if (!unpack->BufferObj) {
404*61046927SAndroid Build Coastguard Worker       /* no PBO */
405*61046927SAndroid Build Coastguard Worker       return pixels;
406*61046927SAndroid Build Coastguard Worker    }
407*61046927SAndroid Build Coastguard Worker    if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
408*61046927SAndroid Build Coastguard Worker                                   format, type, INT_MAX, pixels)) {
409*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)",
410*61046927SAndroid Build Coastguard Worker                   funcName, dimensions);
411*61046927SAndroid Build Coastguard Worker       return NULL;
412*61046927SAndroid Build Coastguard Worker    }
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker    buf = (GLubyte *) _mesa_bufferobj_map_range(ctx, 0,
415*61046927SAndroid Build Coastguard Worker                                                unpack->BufferObj->Size,
416*61046927SAndroid Build Coastguard Worker                                                GL_MAP_READ_BIT,
417*61046927SAndroid Build Coastguard Worker                                                unpack->BufferObj,
418*61046927SAndroid Build Coastguard Worker                                                MAP_INTERNAL);
419*61046927SAndroid Build Coastguard Worker    if (!buf) {
420*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName,
421*61046927SAndroid Build Coastguard Worker                   dimensions);
422*61046927SAndroid Build Coastguard Worker       return NULL;
423*61046927SAndroid Build Coastguard Worker    }
424*61046927SAndroid Build Coastguard Worker 
425*61046927SAndroid Build Coastguard Worker    return ADD_POINTERS(buf, pixels);
426*61046927SAndroid Build Coastguard Worker }
427*61046927SAndroid Build Coastguard Worker 
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker /**
430*61046927SAndroid Build Coastguard Worker  * Check if an unpack PBO is active prior to fetching a compressed texture
431*61046927SAndroid Build Coastguard Worker  * image.
432*61046927SAndroid Build Coastguard Worker  * If so, do bounds checking and map the buffer into main memory.
433*61046927SAndroid Build Coastguard Worker  * Any errors detected will be recorded.
434*61046927SAndroid Build Coastguard Worker  * The caller _must_ call _mesa_unmap_teximage_pbo() too!
435*61046927SAndroid Build Coastguard Worker  */
436*61046927SAndroid Build Coastguard Worker const GLvoid *
_mesa_validate_pbo_compressed_teximage(struct gl_context * ctx,GLuint dimensions,GLsizei imageSize,const GLvoid * pixels,const struct gl_pixelstore_attrib * packing,const char * funcName)437*61046927SAndroid Build Coastguard Worker _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
438*61046927SAndroid Build Coastguard Worker                                  GLuint dimensions, GLsizei imageSize,
439*61046927SAndroid Build Coastguard Worker                                  const GLvoid *pixels,
440*61046927SAndroid Build Coastguard Worker                                  const struct gl_pixelstore_attrib *packing,
441*61046927SAndroid Build Coastguard Worker                                  const char *funcName)
442*61046927SAndroid Build Coastguard Worker {
443*61046927SAndroid Build Coastguard Worker    GLubyte *buf;
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker    if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, packing,
446*61046927SAndroid Build Coastguard Worker                                              imageSize, pixels, funcName)) {
447*61046927SAndroid Build Coastguard Worker      /* error is already set during validation */
448*61046927SAndroid Build Coastguard Worker       return NULL;
449*61046927SAndroid Build Coastguard Worker    }
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker    if (!packing->BufferObj) {
452*61046927SAndroid Build Coastguard Worker       /* not using a PBO - return pointer unchanged */
453*61046927SAndroid Build Coastguard Worker       return pixels;
454*61046927SAndroid Build Coastguard Worker    }
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker    buf = (GLubyte*) _mesa_bufferobj_map_range(ctx, 0,
457*61046927SAndroid Build Coastguard Worker                                               packing->BufferObj->Size,
458*61046927SAndroid Build Coastguard Worker                                               GL_MAP_READ_BIT,
459*61046927SAndroid Build Coastguard Worker                                               packing->BufferObj,
460*61046927SAndroid Build Coastguard Worker                                               MAP_INTERNAL);
461*61046927SAndroid Build Coastguard Worker 
462*61046927SAndroid Build Coastguard Worker    /* Validation above already checked that PBO is not mapped, so buffer
463*61046927SAndroid Build Coastguard Worker     * should not be null.
464*61046927SAndroid Build Coastguard Worker     */
465*61046927SAndroid Build Coastguard Worker    assert(buf);
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker    return ADD_POINTERS(buf, pixels);
468*61046927SAndroid Build Coastguard Worker }
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker 
471*61046927SAndroid Build Coastguard Worker /**
472*61046927SAndroid Build Coastguard Worker  * This function must be called after either of the validate_pbo_*_teximage()
473*61046927SAndroid Build Coastguard Worker  * functions.  It unmaps the PBO buffer if it was mapped earlier.
474*61046927SAndroid Build Coastguard Worker  */
475*61046927SAndroid Build Coastguard Worker void
_mesa_unmap_teximage_pbo(struct gl_context * ctx,const struct gl_pixelstore_attrib * unpack)476*61046927SAndroid Build Coastguard Worker _mesa_unmap_teximage_pbo(struct gl_context *ctx,
477*61046927SAndroid Build Coastguard Worker                          const struct gl_pixelstore_attrib *unpack)
478*61046927SAndroid Build Coastguard Worker {
479*61046927SAndroid Build Coastguard Worker    if (unpack->BufferObj) {
480*61046927SAndroid Build Coastguard Worker       _mesa_bufferobj_unmap(ctx, unpack->BufferObj, MAP_INTERNAL);
481*61046927SAndroid Build Coastguard Worker    }
482*61046927SAndroid Build Coastguard Worker }
483