b32310c309186f65068a5a656bc2a2049a0b613a
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
, int depth
,
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
->ImageHeight
!= 0 && packing
->ImageHeight
!= height
) ||
66 pbo_format
= _mesa_format_from_format_and_type(format
, type
);
67 if (_mesa_format_is_mesa_array_format(pbo_format
))
68 pbo_format
= _mesa_format_from_array_format(pbo_format
);
70 if (!pbo_format
|| !ctx
->TextureFormatSupported
[pbo_format
])
73 /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
74 pixels
= _mesa_image_address3d(packing
, pixels
,
75 width
, height
, format
, type
, 0, 0, 0);
76 row_stride
= _mesa_image_row_stride(packing
, width
, format
, type
);
78 if (_mesa_is_bufferobj(packing
->BufferObj
)) {
80 buffer_obj
= packing
->BufferObj
;
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
);
92 _mesa_BufferData(pbo_target
, row_stride
* height
, pixels
, GL_STREAM_DRAW
);
94 buffer_obj
= ctx
->Unpack
.BufferObj
;
97 _mesa_BindBuffer(pbo_target
, 0);
100 _mesa_GenTextures(1, tmp_tex
);
101 tex_obj
= _mesa_lookup_texture(ctx
, *tmp_tex
);
102 tex_obj
->Target
= depth
> 1 ? GL_TEXTURE_2D_ARRAY
: GL_TEXTURE_2D
;
103 tex_obj
->Immutable
= GL_TRUE
;
104 _mesa_initialize_texture_object(ctx
, tex_obj
, *tmp_tex
, GL_TEXTURE_2D
);
106 internal_format
= _mesa_get_format_base_format(pbo_format
);
108 tex_image
= _mesa_get_tex_image(ctx
, tex_obj
, tex_obj
->Target
, 0);
109 _mesa_init_teximage_fields(ctx
, tex_image
, width
, height
, depth
,
110 0, internal_format
, pbo_format
);
112 read_only
= pbo_target
== GL_PIXEL_UNPACK_BUFFER
;
113 if (!ctx
->Driver
.SetTextureStorageForBufferObject(ctx
, tex_obj
,
118 _mesa_DeleteTextures(1, tmp_tex
);
119 _mesa_DeleteBuffers(1, tmp_pbo
);
127 _mesa_meta_pbo_TexSubImage(struct gl_context
*ctx
, GLuint dims
,
128 struct gl_texture_image
*tex_image
,
129 int xoffset
, int yoffset
, int zoffset
,
130 int width
, int height
, int depth
,
131 GLenum format
, GLenum type
, const void *pixels
,
132 bool allocate_storage
, bool create_pbo
,
133 const struct gl_pixelstore_attrib
*packing
)
135 GLuint pbo
= 0, pbo_tex
= 0, fbos
[2] = { 0, 0 };
136 struct gl_texture_image
*pbo_tex_image
;
138 bool success
= false;
140 /* XXX: This should probably be passed in from somewhere */
141 const char *where
= "_mesa_meta_pbo_TexSubImage";
143 if (!_mesa_is_bufferobj(packing
->BufferObj
) && !create_pbo
)
146 if (format
== GL_DEPTH_COMPONENT
||
147 format
== GL_DEPTH_STENCIL
||
148 format
== GL_STENCIL_INDEX
||
149 format
== GL_COLOR_INDEX
)
152 if (ctx
->_ImageTransferState
)
155 if (!_mesa_validate_pbo_access(dims
, packing
, width
, height
, depth
,
156 format
, type
, INT_MAX
, pixels
)) {
157 _mesa_error(ctx
, GL_INVALID_OPERATION
,
158 "%s(out of bounds PBO access)", where
);
162 if (_mesa_check_disallowed_mapping(packing
->BufferObj
)) {
163 /* buffer is mapped - that's an error */
164 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(PBO is mapped)", where
);
168 pbo_tex_image
= create_texture_for_pbo(ctx
, create_pbo
,
169 GL_PIXEL_UNPACK_BUFFER
,
170 width
, height
, depth
,
171 format
, type
, pixels
, packing
,
176 if (allocate_storage
)
177 ctx
->Driver
.AllocTextureImageBuffer(ctx
, tex_image
);
179 /* Only stash the current FBO */
180 _mesa_meta_begin(ctx
, 0);
182 _mesa_GenFramebuffers(2, fbos
);
183 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
184 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
186 if (tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
) {
192 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
194 /* If this passes on the first layer it should pass on the others */
195 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
196 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
199 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
201 /* If this passes on the first layer it should pass on the others */
202 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
203 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
206 _mesa_update_state(ctx
);
208 if (_mesa_meta_BlitFramebuffer(ctx
, 0, 0, width
, height
,
210 xoffset
+ width
, yoffset
+ height
,
211 GL_COLOR_BUFFER_BIT
, GL_NEAREST
))
214 for (int z
= 1; z
< depth
; z
++) {
215 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
217 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
218 tex_image
, zoffset
+ z
);
220 _mesa_update_state(ctx
);
222 _mesa_meta_BlitFramebuffer(ctx
, 0, 0, width
, height
,
224 xoffset
+ width
, yoffset
+ height
,
225 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
231 _mesa_DeleteFramebuffers(2, fbos
);
232 _mesa_DeleteTextures(1, &pbo_tex
);
233 _mesa_DeleteBuffers(1, &pbo
);
241 _mesa_meta_pbo_GetTexSubImage(struct gl_context
*ctx
, GLuint dims
,
242 struct gl_texture_image
*tex_image
,
243 int xoffset
, int yoffset
, int zoffset
,
244 int width
, int height
, int depth
,
245 GLenum format
, GLenum type
, const void *pixels
,
246 const struct gl_pixelstore_attrib
*packing
)
248 GLuint pbo
= 0, pbo_tex
= 0, fbos
[2] = { 0, 0 };
249 struct gl_texture_image
*pbo_tex_image
;
251 bool success
= false;
253 /* XXX: This should probably be passed in from somewhere */
254 const char *where
= "_mesa_meta_pbo_GetTexSubImage";
256 if (!_mesa_is_bufferobj(packing
->BufferObj
))
259 if (format
== GL_DEPTH_COMPONENT
||
260 format
== GL_DEPTH_STENCIL
||
261 format
== GL_STENCIL_INDEX
||
262 format
== GL_COLOR_INDEX
)
265 if (ctx
->_ImageTransferState
)
268 if (!_mesa_validate_pbo_access(dims
, packing
, width
, height
, depth
,
269 format
, type
, INT_MAX
, pixels
)) {
270 _mesa_error(ctx
, GL_INVALID_OPERATION
,
271 "%s(out of bounds PBO access)", where
);
275 if (_mesa_check_disallowed_mapping(packing
->BufferObj
)) {
276 /* buffer is mapped - that's an error */
277 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(PBO is mapped)", where
);
281 pbo_tex_image
= create_texture_for_pbo(ctx
, false, GL_PIXEL_PACK_BUFFER
,
282 width
, height
, depth
,
283 format
, type
, pixels
, packing
,
288 /* Only stash the current FBO */
289 _mesa_meta_begin(ctx
, 0);
291 _mesa_GenFramebuffers(2, fbos
);
293 if (tex_image
&& tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
) {
299 /* If we were given a texture, bind it to the read framebuffer. If not,
300 * we're doing a ReadPixels and we should just use whatever framebuffer
301 * the client has bound.
304 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
305 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
307 /* If this passes on the first layer it should pass on the others */
308 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
309 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
315 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
316 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
318 /* If this passes on the first layer it should pass on the others */
319 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
320 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
323 _mesa_update_state(ctx
);
325 if (_mesa_meta_BlitFramebuffer(ctx
, xoffset
, yoffset
,
326 xoffset
+ width
, yoffset
+ height
,
328 GL_COLOR_BUFFER_BIT
, GL_NEAREST
))
331 for (int z
= 1; z
< depth
; z
++) {
332 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
333 tex_image
, zoffset
+ z
);
334 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
337 _mesa_update_state(ctx
);
339 _mesa_meta_BlitFramebuffer(ctx
, xoffset
, yoffset
,
340 xoffset
+ width
, yoffset
+ height
,
342 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
348 _mesa_DeleteFramebuffers(2, fbos
);
349 _mesa_DeleteTextures(1, &pbo_tex
);
350 _mesa_DeleteBuffers(1, &pbo
);