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
);
92 /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel
93 * data to avoid unnecessary data copying in _mesa_BufferData().
96 _mesa_BufferData(pbo_target
, row_stride
* height
, NULL
,
99 _mesa_BufferData(pbo_target
, row_stride
* height
, pixels
,
102 buffer_obj
= packing
->BufferObj
;
105 _mesa_BindBuffer(pbo_target
, 0);
108 _mesa_GenTextures(1, tmp_tex
);
109 tex_obj
= _mesa_lookup_texture(ctx
, *tmp_tex
);
110 _mesa_initialize_texture_object(ctx
, tex_obj
, *tmp_tex
, GL_TEXTURE_2D
);
111 /* This must be set after _mesa_initialize_texture_object, not before. */
112 tex_obj
->Immutable
= GL_TRUE
;
113 /* This is required for interactions with ARB_texture_view. */
114 tex_obj
->NumLayers
= 1;
116 internal_format
= _mesa_get_format_base_format(pbo_format
);
118 tex_image
= _mesa_get_tex_image(ctx
, tex_obj
, tex_obj
->Target
, 0);
119 _mesa_init_teximage_fields(ctx
, tex_image
, width
, height
, 1,
120 0, internal_format
, pbo_format
);
122 read_only
= pbo_target
== GL_PIXEL_UNPACK_BUFFER
;
123 if (!ctx
->Driver
.SetTextureStorageForBufferObject(ctx
, tex_obj
,
128 _mesa_DeleteTextures(1, tmp_tex
);
129 _mesa_DeleteBuffers(1, tmp_pbo
);
137 _mesa_meta_pbo_TexSubImage(struct gl_context
*ctx
, GLuint dims
,
138 struct gl_texture_image
*tex_image
,
139 int xoffset
, int yoffset
, int zoffset
,
140 int width
, int height
, int depth
,
141 GLenum format
, GLenum type
, const void *pixels
,
142 bool allocate_storage
, bool create_pbo
,
143 const struct gl_pixelstore_attrib
*packing
)
145 GLuint pbo
= 0, pbo_tex
= 0, fbos
[2] = { 0, 0 };
146 struct gl_texture_image
*pbo_tex_image
;
148 bool success
= false;
151 /* XXX: This should probably be passed in from somewhere */
152 const char *where
= "_mesa_meta_pbo_TexSubImage";
154 if (!_mesa_is_bufferobj(packing
->BufferObj
) && !create_pbo
)
157 if (format
== GL_DEPTH_COMPONENT
||
158 format
== GL_DEPTH_STENCIL
||
159 format
== GL_STENCIL_INDEX
||
160 format
== GL_COLOR_INDEX
)
163 if (ctx
->_ImageTransferState
)
166 if (!_mesa_validate_pbo_access(dims
, packing
, width
, height
, depth
,
167 format
, type
, INT_MAX
, pixels
)) {
168 _mesa_error(ctx
, GL_INVALID_OPERATION
,
169 "%s(out of bounds PBO access)", where
);
173 if (_mesa_check_disallowed_mapping(packing
->BufferObj
)) {
174 /* buffer is mapped - that's an error */
175 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(PBO is mapped)", where
);
179 /* Only accept tightly packed pixels from the user. */
180 if (packing
->ImageHeight
!= 0 && packing
->ImageHeight
!= height
)
183 /* For arrays, use a tall (height * depth) 2D texture. */
184 pbo_tex_image
= create_texture_for_pbo(ctx
, create_pbo
,
185 GL_PIXEL_UNPACK_BUFFER
,
186 width
, height
* depth
,
187 format
, type
, pixels
, packing
,
192 if (allocate_storage
)
193 ctx
->Driver
.AllocTextureImageBuffer(ctx
, tex_image
);
195 /* Only stash the current FBO */
196 _mesa_meta_begin(ctx
, 0);
198 _mesa_GenFramebuffers(2, fbos
);
199 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
200 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
202 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
204 /* If this passes on the first layer it should pass on the others */
205 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
206 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
209 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
211 /* If this passes on the first layer it should pass on the others */
212 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
213 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
216 _mesa_update_state(ctx
);
218 if (_mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
221 xoffset
+ width
, yoffset
+ height
,
222 GL_COLOR_BUFFER_BIT
, GL_NEAREST
))
225 iters
= tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
?
228 for (z
= 1; z
< iters
; z
++) {
229 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
231 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
232 tex_image
, zoffset
+ z
);
234 _mesa_update_state(ctx
);
236 if (tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
237 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
240 xoffset
+ width
, yoffset
+ 1,
241 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
243 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
244 0, z
* height
, width
, (z
+ 1) * height
,
246 xoffset
+ width
, yoffset
+ height
,
247 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
253 _mesa_DeleteFramebuffers(2, fbos
);
254 _mesa_DeleteTextures(1, &pbo_tex
);
255 _mesa_DeleteBuffers(1, &pbo
);
263 _mesa_meta_pbo_GetTexSubImage(struct gl_context
*ctx
, GLuint dims
,
264 struct gl_texture_image
*tex_image
,
265 int xoffset
, int yoffset
, int zoffset
,
266 int width
, int height
, int depth
,
267 GLenum format
, GLenum type
, const void *pixels
,
268 const struct gl_pixelstore_attrib
*packing
)
270 GLuint pbo
= 0, pbo_tex
= 0, fbos
[2] = { 0, 0 };
271 struct gl_texture_image
*pbo_tex_image
;
273 bool success
= false;
276 /* XXX: This should probably be passed in from somewhere */
277 const char *where
= "_mesa_meta_pbo_GetTexSubImage";
279 if (!_mesa_is_bufferobj(packing
->BufferObj
))
282 if (format
== GL_DEPTH_COMPONENT
||
283 format
== GL_DEPTH_STENCIL
||
284 format
== GL_STENCIL_INDEX
||
285 format
== GL_COLOR_INDEX
)
288 if (ctx
->_ImageTransferState
)
291 if (!_mesa_validate_pbo_access(dims
, packing
, width
, height
, depth
,
292 format
, type
, INT_MAX
, pixels
)) {
293 _mesa_error(ctx
, GL_INVALID_OPERATION
,
294 "%s(out of bounds PBO access)", where
);
298 if (_mesa_check_disallowed_mapping(packing
->BufferObj
)) {
299 /* buffer is mapped - that's an error */
300 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(PBO is mapped)", where
);
304 /* Only accept tightly packed pixels from the user. */
305 if (packing
->ImageHeight
!= 0 && packing
->ImageHeight
!= height
)
308 /* For arrays, use a tall (height * depth) 2D texture. */
309 pbo_tex_image
= create_texture_for_pbo(ctx
, false, GL_PIXEL_PACK_BUFFER
,
310 width
, height
* depth
,
311 format
, type
, pixels
, packing
,
316 /* Only stash the current FBO */
317 _mesa_meta_begin(ctx
, 0);
319 _mesa_GenFramebuffers(2, fbos
);
321 /* If we were given a texture, bind it to the read framebuffer. If not,
322 * we're doing a ReadPixels and we should just use whatever framebuffer
323 * the client has bound.
326 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER
, fbos
[0]);
327 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
329 /* If this passes on the first layer it should pass on the others */
330 status
= _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER
);
331 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
337 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbos
[1]);
338 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
340 /* If this passes on the first layer it should pass on the others */
341 status
= _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER
);
342 if (status
!= GL_FRAMEBUFFER_COMPLETE
)
345 _mesa_update_state(ctx
);
347 if (_mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
349 xoffset
+ width
, yoffset
+ height
,
351 GL_COLOR_BUFFER_BIT
, GL_NEAREST
))
354 if (tex_image
&& tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
359 for (z
= 1; z
< iters
; z
++) {
360 _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
361 tex_image
, zoffset
+ z
);
362 _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
365 _mesa_update_state(ctx
);
367 if (tex_image
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
368 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
370 xoffset
+ width
, yoffset
+ 1,
372 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
374 _mesa_meta_BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
376 xoffset
+ width
, yoffset
+ height
,
377 0, z
* height
, width
, (z
+ 1) * height
,
378 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
384 _mesa_DeleteFramebuffers(2, fbos
);
385 _mesa_DeleteTextures(1, &pbo_tex
);
386 _mesa_DeleteBuffers(1, &pbo
);