2 * Mesa 3-D graphics library
4 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 * Jason Ekstrand <jason.ekstrand@intel.com>
28 #include "bufferobj.h"
31 #include "glformats.h"
37 #include "shaderapi.h"
45 static struct gl_texture_image
*
46 create_texture_for_pbo(struct gl_context
*ctx
, bool create_pbo
,
47 GLenum pbo_target
, int width
, int height
,
48 GLenum format
, GLenum type
, const void *pixels
,
49 const struct gl_pixelstore_attrib
*packing
,
50 GLuint
*tmp_pbo
, GLuint
*tmp_tex
)
53 GLenum internal_format
;
55 struct gl_buffer_object
*buffer_obj
;
56 struct gl_texture_object
*tex_obj
;
57 struct gl_texture_image
*tex_image
;
60 if (packing
->SwapBytes
||
65 pbo_format
= _mesa_format_from_format_and_type(format
, type
);
66 if (_mesa_format_is_mesa_array_format(pbo_format
))
67 pbo_format
= _mesa_format_from_array_format(pbo_format
);
69 if (!pbo_format
|| !ctx
->TextureFormatSupported
[pbo_format
])
72 /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
73 pixels
= _mesa_image_address3d(packing
, pixels
,
74 width
, height
, format
, type
, 0, 0, 0);
75 row_stride
= _mesa_image_row_stride(packing
, width
, format
, type
);
77 if (_mesa_is_bufferobj(packing
->BufferObj
)) {
79 buffer_obj
= packing
->BufferObj
;
82 bool is_pixel_pack
= pbo_target
== GL_PIXEL_PACK_BUFFER
;
84 _mesa_GenBuffers(1, tmp_pbo
);
86 /* We are not doing this inside meta_begin/end. However, we know the
87 * client doesn't have the given target bound, so we can go ahead and
88 * squash it. We'll set it back when we're done.
90 _mesa_BindBuffer(pbo_target
, *tmp_pbo
);
93 _mesa_BufferData(pbo_target
, row_stride
* height
, pixels
,
96 _mesa_BufferData(pbo_target
, row_stride
* height
, pixels
,
99 buffer_obj
= packing
->BufferObj
;
102 _mesa_BindBuffer(pbo_target
, 0);
105 _mesa_GenTextures(1, tmp_tex
);
106 tex_obj
= _mesa_lookup_texture(ctx
, *tmp_tex
);
107 _mesa_initialize_texture_object(ctx
, tex_obj
, *tmp_tex
, GL_TEXTURE_2D
);
108 /* This must be set after _mesa_initialize_texture_object, not before. */
109 tex_obj
->Immutable
= GL_TRUE
;
110 /* This is required for interactions with ARB_texture_view. */
111 tex_obj
->NumLayers
= 1;
113 internal_format
= _mesa_get_format_base_format(pbo_format
);
115 tex_image
= _mesa_get_tex_image(ctx
, tex_obj
, tex_obj
->Target
, 0);
116 _mesa_init_teximage_fields(ctx
, tex_image
, width
, height
, 1,
117 0, internal_format
, pbo_format
);
119 read_only
= pbo_target
== GL_PIXEL_UNPACK_BUFFER
;
120 if (!ctx
->Driver
.SetTextureStorageForBufferObject(ctx
, tex_obj
,
125 _mesa_DeleteTextures(1, tmp_tex
);
126 _mesa_DeleteBuffers(1, tmp_pbo
);
134 _mesa_meta_pbo_TexSubImage(struct gl_context
*ctx
, GLuint dims
,
135 struct gl_texture_image
*tex_image
,
136 int xoffset
, int yoffset
, int zoffset
,
137 int width
, int height
, int depth
,
138 GLenum format
, GLenum type
, const void *pixels
,
139 bool allocate_storage
, bool create_pbo
,
140 const struct gl_pixelstore_attrib
*packing
)
142 GLuint pbo
= 0, pbo_tex
= 0, fbos
[2] = { 0, 0 };
143 struct gl_texture_image
*pbo_tex_image
;
145 bool success
= false;
148 /* XXX: This should probably be passed in from somewhere */
149 const char *where
= "_mesa_meta_pbo_TexSubImage";
151 if (!_mesa_is_bufferobj(packing
->BufferObj
) && !create_pbo
)
154 if (format
== GL_DEPTH_COMPONENT
||
155 format
== GL_DEPTH_STENCIL
||
156 format
== GL_STENCIL_INDEX
||
157 format
== GL_COLOR_INDEX
)
160 if (ctx
->_ImageTransferState
)
163 if (!_mesa_validate_pbo_access(dims
, packing
, width
, height
, depth
,
164 format
, type
, INT_MAX
, pixels
)) {
165 _mesa_error(ctx
, GL_INVALID_OPERATION
,
166 "%s(out of bounds PBO access)", where
);
170 if (_mesa_check_disallowed_mapping(packing
->BufferObj
)) {
171 /* buffer is mapped - that's an error */
172 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(PBO is mapped)", where
);
176 /* Only accept tightly packed pixels from the user. */
177 if (packing
->ImageHeight
!= 0 && packing
->ImageHeight
!= height
)
180 /* For arrays, use a tall (height * depth) 2D texture. */
181 pbo_tex_image
= create_texture_for_pbo(ctx
, create_pbo
,
182 GL_PIXEL_UNPACK_BUFFER
,
183 width
, height
* depth
,
184 format
, type
, pixels
, packing
,
189 if (allocate_storage
)
190 ctx
->Driver
.AllocTextureImageBuffer(ctx
, tex_image
);
192 /* Only stash the current FBO */
193 _mesa_meta_begin(ctx
, 0);
195 _mesa_GenFramebuffers(2, fbos
);
196 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
197 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
199 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
201 /* If this passes on the first layer it should pass on the others */
202 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
203 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
206 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
208 /* If this passes on the first layer it should pass on the others */
209 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
210 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
213 _mesa_update_state(ctx
);
215 if (_mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
218 xoffset
+ width
, yoffset
+ height
,
219 GL_COLOR_BUFFER_BIT
, GL_NEAREST
))
222 iters
= tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
?
225 for (z
= 1; z
< iters
; z
++) {
226 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
228 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
229 tex_image
, zoffset
+ z
);
231 _mesa_update_state(ctx
);
233 if (tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
234 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
237 xoffset
+ width
, yoffset
+ 1,
238 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
240 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
241 0, z
* height
, width
, (z
+ 1) * height
,
243 xoffset
+ width
, yoffset
+ height
,
244 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
250 _mesa_DeleteFramebuffers(2, fbos
);
251 _mesa_DeleteTextures(1, &pbo_tex
);
252 _mesa_DeleteBuffers(1, &pbo
);
260 _mesa_meta_pbo_GetTexSubImage(struct gl_context
*ctx
, GLuint dims
,
261 struct gl_texture_image
*tex_image
,
262 int xoffset
, int yoffset
, int zoffset
,
263 int width
, int height
, int depth
,
264 GLenum format
, GLenum type
, const void *pixels
,
265 const struct gl_pixelstore_attrib
*packing
)
267 GLuint pbo
= 0, pbo_tex
= 0, fbos
[2] = { 0, 0 };
268 struct gl_texture_image
*pbo_tex_image
;
270 bool success
= false;
273 /* XXX: This should probably be passed in from somewhere */
274 const char *where
= "_mesa_meta_pbo_GetTexSubImage";
276 if (!_mesa_is_bufferobj(packing
->BufferObj
))
279 if (format
== GL_DEPTH_COMPONENT
||
280 format
== GL_DEPTH_STENCIL
||
281 format
== GL_STENCIL_INDEX
||
282 format
== GL_COLOR_INDEX
)
285 if (ctx
->_ImageTransferState
)
288 if (!_mesa_validate_pbo_access(dims
, packing
, width
, height
, depth
,
289 format
, type
, INT_MAX
, pixels
)) {
290 _mesa_error(ctx
, GL_INVALID_OPERATION
,
291 "%s(out of bounds PBO access)", where
);
295 if (_mesa_check_disallowed_mapping(packing
->BufferObj
)) {
296 /* buffer is mapped - that's an error */
297 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(PBO is mapped)", where
);
301 /* Only accept tightly packed pixels from the user. */
302 if (packing
->ImageHeight
!= 0 && packing
->ImageHeight
!= height
)
305 /* For arrays, use a tall (height * depth) 2D texture. */
306 pbo_tex_image
= create_texture_for_pbo(ctx
, false, GL_PIXEL_PACK_BUFFER
,
307 width
, height
* depth
,
308 format
, type
, pixels
, packing
,
313 /* Only stash the current FBO */
314 _mesa_meta_begin(ctx
, 0);
316 _mesa_GenFramebuffers(2, fbos
);
318 /* If we were given a texture, bind it to the read framebuffer. If not,
319 * we're doing a ReadPixels and we should just use whatever framebuffer
320 * the client has bound.
323 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
324 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
326 /* If this passes on the first layer it should pass on the others */
327 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
328 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
334 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
335 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
337 /* If this passes on the first layer it should pass on the others */
338 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
339 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
342 _mesa_update_state(ctx
);
344 if (_mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
346 xoffset
+ width
, yoffset
+ height
,
348 GL_COLOR_BUFFER_BIT
, GL_NEAREST
))
351 if (tex_image
&& tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
356 for (z
= 1; z
< iters
; z
++) {
357 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
358 tex_image
, zoffset
+ z
);
359 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
362 _mesa_update_state(ctx
);
364 if (tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
365 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
367 xoffset
+ width
, yoffset
+ 1,
369 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
371 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
373 xoffset
+ width
, yoffset
+ height
,
374 0, z
* height
, width
, (z
+ 1) * height
,
375 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
381 _mesa_DeleteFramebuffers(2, fbos
);
382 _mesa_DeleteTextures(1, &pbo_tex
);
383 _mesa_DeleteBuffers(1, &pbo
);