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
;
81 bool is_pixel_pack
= pbo_target
== GL_PIXEL_PACK_BUFFER
;
85 _mesa_GenBuffers(1, tmp_pbo
);
87 /* We are not doing this inside meta_begin/end. However, we know the
88 * client doesn't have the given target bound, so we can go ahead and
89 * squash it. We'll set it back when we're done.
91 _mesa_BindBuffer(pbo_target
, *tmp_pbo
);
93 /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel
94 * data to avoid unnecessary data copying in _mesa_BufferData().
97 _mesa_BufferData(pbo_target
, row_stride
* height
, NULL
,
100 _mesa_BufferData(pbo_target
, row_stride
* height
, pixels
,
103 buffer_obj
= packing
->BufferObj
;
106 _mesa_BindBuffer(pbo_target
, 0);
109 _mesa_GenTextures(1, tmp_tex
);
110 tex_obj
= _mesa_lookup_texture(ctx
, *tmp_tex
);
111 _mesa_initialize_texture_object(ctx
, tex_obj
, *tmp_tex
, GL_TEXTURE_2D
);
112 /* This must be set after _mesa_initialize_texture_object, not before. */
113 tex_obj
->Immutable
= GL_TRUE
;
114 /* This is required for interactions with ARB_texture_view. */
115 tex_obj
->NumLayers
= 1;
117 internal_format
= _mesa_get_format_base_format(pbo_format
);
119 tex_image
= _mesa_get_tex_image(ctx
, tex_obj
, tex_obj
->Target
, 0);
120 _mesa_init_teximage_fields(ctx
, tex_image
, width
, height
, 1,
121 0, internal_format
, pbo_format
);
123 read_only
= pbo_target
== GL_PIXEL_UNPACK_BUFFER
;
124 if (!ctx
->Driver
.SetTextureStorageForBufferObject(ctx
, tex_obj
,
129 _mesa_DeleteTextures(1, tmp_tex
);
130 _mesa_DeleteBuffers(1, tmp_pbo
);
138 _mesa_meta_pbo_TexSubImage(struct gl_context
*ctx
, GLuint dims
,
139 struct gl_texture_image
*tex_image
,
140 int xoffset
, int yoffset
, int zoffset
,
141 int width
, int height
, int depth
,
142 GLenum format
, GLenum type
, const void *pixels
,
143 bool allocate_storage
, bool create_pbo
,
144 const struct gl_pixelstore_attrib
*packing
)
146 GLuint pbo
= 0, pbo_tex
= 0, fbos
[2] = { 0, 0 };
147 int full_height
, image_height
;
148 struct gl_texture_image
*pbo_tex_image
;
150 bool success
= false;
153 /* XXX: This should probably be passed in from somewhere */
154 const char *where
= "_mesa_meta_pbo_TexSubImage";
156 if (!_mesa_is_bufferobj(packing
->BufferObj
) && !create_pbo
)
159 if (format
== GL_DEPTH_COMPONENT
||
160 format
== GL_DEPTH_STENCIL
||
161 format
== GL_STENCIL_INDEX
||
162 format
== GL_COLOR_INDEX
)
165 if (ctx
->_ImageTransferState
)
168 if (!_mesa_validate_pbo_access(dims
, packing
, width
, height
, depth
,
169 format
, type
, INT_MAX
, pixels
)) {
170 _mesa_error(ctx
, GL_INVALID_OPERATION
,
171 "%s(out of bounds PBO access)", where
);
175 if (_mesa_check_disallowed_mapping(packing
->BufferObj
)) {
176 /* buffer is mapped - that's an error */
177 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(PBO is mapped)", where
);
181 /* For arrays, use a tall (height * depth) 2D texture but taking into
182 * account the inter-image padding specified with the image height packing
185 image_height
= packing
->ImageHeight
== 0 ? height
: packing
->ImageHeight
;
186 full_height
= image_height
* (depth
- 1) + height
;
188 pbo_tex_image
= create_texture_for_pbo(ctx
, create_pbo
,
189 GL_PIXEL_UNPACK_BUFFER
,
191 format
, type
, pixels
, packing
,
196 if (allocate_storage
)
197 ctx
->Driver
.AllocTextureImageBuffer(ctx
, tex_image
);
199 _mesa_meta_begin(ctx
, ~(MESA_META_PIXEL_TRANSFER
|
200 MESA_META_PIXEL_STORE
));
202 _mesa_GenFramebuffers(2, fbos
);
203 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
204 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
206 if (tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
) {
208 assert(zoffset
== 0);
216 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
218 /* If this passes on the first layer it should pass on the others */
219 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
220 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
223 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
225 /* If this passes on the first layer it should pass on the others */
226 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
227 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
230 _mesa_update_state(ctx
);
232 if (_mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
235 xoffset
+ width
, yoffset
+ height
,
236 GL_COLOR_BUFFER_BIT
, GL_NEAREST
))
239 for (z
= 1; z
< depth
; z
++) {
240 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
241 tex_image
, zoffset
+ z
);
243 _mesa_update_state(ctx
);
245 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
247 width
, z
* image_height
+ height
,
249 xoffset
+ width
, yoffset
+ height
,
250 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
256 _mesa_DeleteFramebuffers(2, fbos
);
257 _mesa_DeleteTextures(1, &pbo_tex
);
258 _mesa_DeleteBuffers(1, &pbo
);
266 _mesa_meta_pbo_GetTexSubImage(struct gl_context
*ctx
, GLuint dims
,
267 struct gl_texture_image
*tex_image
,
268 int xoffset
, int yoffset
, int zoffset
,
269 int width
, int height
, int depth
,
270 GLenum format
, GLenum type
, const void *pixels
,
271 const struct gl_pixelstore_attrib
*packing
)
273 GLuint pbo
= 0, pbo_tex
= 0, fbos
[2] = { 0, 0 };
274 int full_height
, image_height
;
275 struct gl_texture_image
*pbo_tex_image
;
277 bool success
= false;
280 /* XXX: This should probably be passed in from somewhere */
281 const char *where
= "_mesa_meta_pbo_GetTexSubImage";
283 if (!_mesa_is_bufferobj(packing
->BufferObj
))
286 if (format
== GL_DEPTH_COMPONENT
||
287 format
== GL_DEPTH_STENCIL
||
288 format
== GL_STENCIL_INDEX
||
289 format
== GL_COLOR_INDEX
)
292 if (ctx
->_ImageTransferState
)
295 if (!_mesa_validate_pbo_access(dims
, packing
, width
, height
, depth
,
296 format
, type
, INT_MAX
, pixels
)) {
297 _mesa_error(ctx
, GL_INVALID_OPERATION
,
298 "%s(out of bounds PBO access)", where
);
302 if (_mesa_check_disallowed_mapping(packing
->BufferObj
)) {
303 /* buffer is mapped - that's an error */
304 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(PBO is mapped)", where
);
308 /* For arrays, use a tall (height * depth) 2D texture but taking into
309 * account the inter-image padding specified with the image height packing
312 image_height
= packing
->ImageHeight
== 0 ? height
: packing
->ImageHeight
;
313 full_height
= image_height
* (depth
- 1) + height
;
315 pbo_tex_image
= create_texture_for_pbo(ctx
, false, GL_PIXEL_PACK_BUFFER
,
316 width
, full_height
* depth
,
317 format
, type
, pixels
, packing
,
322 _mesa_meta_begin(ctx
, ~(MESA_META_PIXEL_TRANSFER
|
323 MESA_META_PIXEL_STORE
));
325 _mesa_GenFramebuffers(2, fbos
);
327 if (tex_image
&& tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
) {
329 assert(zoffset
== 0);
337 /* If we were given a texture, bind it to the read framebuffer. If not,
338 * we're doing a ReadPixels and we should just use whatever framebuffer
339 * the client has bound.
342 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
343 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
345 /* If this passes on the first layer it should pass on the others */
346 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
347 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
353 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
354 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
356 /* If this passes on the first layer it should pass on the others */
357 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
358 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
361 _mesa_update_state(ctx
);
363 if (_mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
365 xoffset
+ width
, yoffset
+ height
,
367 GL_COLOR_BUFFER_BIT
, GL_NEAREST
))
370 for (z
= 1; z
< depth
; z
++) {
371 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
372 tex_image
, zoffset
+ z
);
374 _mesa_update_state(ctx
);
376 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
378 xoffset
+ width
, yoffset
+ height
,
380 width
, z
* image_height
+ height
,
381 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
387 _mesa_DeleteFramebuffers(2, fbos
);
388 _mesa_DeleteTextures(1, &pbo_tex
);
389 _mesa_DeleteBuffers(1, &pbo
);