/**************************************************************************
- *
+ *
* Copyright 2007 VMware, Inc.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
+ *
**************************************************************************/
#include "main/bufferobj.h"
#include "main/image.h"
#include "main/pbo.h"
-#include "main/imports.h"
+
#include "main/readpix.h"
#include "main/enums.h"
#include "main/framebuffer.h"
#include "util/u_inlines.h"
-#include "util/u_format.h"
+#include "util/format/u_format.h"
#include "cso_cache/cso_context.h"
#include "st_cb_fbo.h"
#include "state_tracker/st_format.h"
#include "state_tracker/st_pbo.h"
#include "state_tracker/st_texture.h"
+#include "state_tracker/st_util.h"
+
/* The readpixels cache caches a blitted staging texture so that back-to-back
* calls to glReadPixels with user pointers require less CPU-GPU synchronization.
if (texture->nr_samples > 1)
return false;
- if (!screen->is_format_supported(screen, dst_format, PIPE_TEXTURE_2D,
- texture->nr_samples,
+ if (!screen->is_format_supported(screen, dst_format, PIPE_BUFFER, 0, 0,
PIPE_BIND_SHADER_IMAGE))
return false;
cso_save_state(cso, (CSO_BIT_FRAGMENT_SAMPLER_VIEWS |
CSO_BIT_FRAGMENT_SAMPLERS |
CSO_BIT_FRAGMENT_IMAGE0 |
+ CSO_BIT_BLEND |
CSO_BIT_VERTEX_ELEMENTS |
CSO_BIT_AUX_VERTEX_BUFFER_SLOT |
CSO_BIT_FRAMEBUFFER |
CSO_BIT_RASTERIZER |
CSO_BIT_DEPTH_STENCIL_ALPHA |
CSO_BIT_STREAM_OUTPUTS |
- CSO_BIT_PAUSE_QUERIES |
+ (st->active_queries ? CSO_BIT_PAUSE_QUERIES : 0) |
+ CSO_BIT_SAMPLE_MASK |
+ CSO_BIT_MIN_SAMPLES |
+ CSO_BIT_RENDER_CONDITION |
CSO_BITS_ALL_SHADERS));
cso_save_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);
+ cso_set_sample_mask(cso, ~0);
+ cso_set_min_samples(cso, 1);
+ cso_set_render_condition(cso, NULL, FALSE, 0);
+
/* Set up the sampler_view */
{
struct pipe_sampler_view templ;
if (view_target != PIPE_TEXTURE_3D) {
templ.u.tex.first_layer = surface->u.tex.first_layer;
- templ.u.tex.last_layer = templ.u.tex.last_layer;
+ templ.u.tex.last_layer = templ.u.tex.first_layer;
} else {
addr.constants.layer_offset = surface->u.tex.first_layer;
}
image.resource = addr.buffer;
image.format = dst_format;
image.access = PIPE_IMAGE_ACCESS_WRITE;
- image.u.buf.first_element = addr.first_element;
- image.u.buf.last_element = addr.last_element;
+ image.shader_access = PIPE_IMAGE_ACCESS_WRITE;
+ image.u.buf.offset = addr.first_element * addr.bytes_per_pixel;
+ image.u.buf.size = (addr.last_element - addr.first_element + 1) *
+ addr.bytes_per_pixel;
cso_set_shader_images(cso, PIPE_SHADER_FRAGMENT, 0, 1, &image);
}
fb.layers = 1;
cso_set_framebuffer(cso, &fb);
+ /* Any blend state would do. Set this just to prevent drivers having
+ * blend == NULL.
+ */
+ cso_set_blend(cso, &st->pbo.upload_blend);
+
cso_set_viewport_dims(cso, fb.width, fb.height, invert_y);
if (invert_y)
/* Set up the fragment shader */
{
- void *fs = st_pbo_get_download_fs(st, view_target);
+ void *fs = st_pbo_get_download_fs(st, view_target, src_format, dst_format);
if (!fs)
goto fail;
return success;
}
-/* Invalidate the readpixels cache to ensure we don't read stale data.
- */
-void st_invalidate_readpix_cache(struct st_context *st)
-{
- pipe_resource_reference(&st->readpix_cache.src, NULL);
- pipe_resource_reference(&st->readpix_cache.cache, NULL);
-}
-
/**
* Create a staging texture and blit the requested region to it.
*/
/* We are creating a texture of the size of the region being read back.
* Need to check for NPOT texture support. */
if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) &&
- (!util_is_power_of_two(width) ||
- !util_is_power_of_two(height)))
+ (!util_is_power_of_two_or_zero(width) ||
+ !util_is_power_of_two_or_zero(height)))
return NULL;
/* create the destination texture */
memset(&dst_templ, 0, sizeof(dst_templ));
dst_templ.target = PIPE_TEXTURE_2D;
dst_templ.format = dst_format;
- dst_templ.bind = PIPE_BIND_TRANSFER_READ;
if (util_format_is_depth_or_stencil(dst_format))
dst_templ.bind |= PIPE_BIND_DEPTH_STENCIL;
else
struct pipe_resource *src;
struct pipe_resource *dst = NULL;
enum pipe_format dst_format, src_format;
- unsigned bind = PIPE_BIND_TRANSFER_READ;
+ unsigned bind;
struct pipe_transfer *tex_xfer;
ubyte *map = NULL;
- bool window;
+ int dst_x, dst_y;
/* Validate state (to be sure we have up-to-date framebuffer surfaces)
* and flush the bitmap cache prior to reading. */
- st_validate_state(st, ST_PIPELINE_RENDER);
+ st_validate_state(st, ST_PIPELINE_UPDATE_FRAMEBUFFER);
st_flush_bitmap_cache(st);
if (!st->prefer_blit_based_texture_transfer) {
if (!src_format ||
!screen->is_format_supported(screen, src_format, src->target,
- src->nr_samples,
+ src->nr_samples, src->nr_storage_samples,
PIPE_BIND_SAMPLER_VIEW)) {
goto fallback;
}
if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)
- bind |= PIPE_BIND_DEPTH_STENCIL;
+ bind = PIPE_BIND_DEPTH_STENCIL;
else
- bind |= PIPE_BIND_RENDER_TARGET;
+ bind = PIPE_BIND_RENDER_TARGET;
/* Choose the destination format by finding the best match
* for the format+type combo. */
goto fallback;
}
- if (st->pbo.download_enabled && _mesa_is_bufferobj(pack->BufferObj)) {
+ if (st->pbo.download_enabled && pack->BufferObj) {
if (try_pbo_readpixels(st, strb,
st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP,
x, y, width, height,
st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP,
width, height, format, src_format, dst_format);
if (dst) {
- window = false;
+ dst_x = x;
+ dst_y = y;
} else {
/* See if the texture format already matches the format and type,
* in which case the memcpy-based fast path will likely be used and
if (!dst)
goto fallback;
- window = true;
+ dst_x = 0;
+ dst_y = 0;
}
/* map resources */
pixels = _mesa_map_pbo_dest(ctx, pack, pixels);
map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ,
- 0, 0, 0, width, height, 1, &tex_xfer);
+ dst_x, dst_y, 0, width, height, 1, &tex_xfer);
if (!map) {
_mesa_unmap_pbo_dest(ctx, pack);
pipe_resource_reference(&dst, NULL);
goto fallback;
}
- if (!window)
- map += y * tex_xfer->stride + x * util_format_get_blocksize(dst_format);
-
/* memcpy data into a user buffer */
{
const uint bytesPerRow = width * util_format_get_blocksize(dst_format);
- GLuint row;
-
- for (row = 0; row < (unsigned) height; row++) {
- void *dest = _mesa_image_address2d(pack, pixels,
- width, height, format,
- type, row, 0);
- memcpy(dest, map, bytesPerRow);
- map += tex_xfer->stride;
+ const int destStride = _mesa_image_row_stride(pack, width, format, type);
+ char *dest = _mesa_image_address2d(pack, pixels,
+ width, height, format,
+ type, 0, 0);
+
+ if (tex_xfer->stride == bytesPerRow && destStride == bytesPerRow) {
+ memcpy(dest, map, bytesPerRow * height);
+ } else {
+ GLuint row;
+
+ for (row = 0; row < (unsigned) height; row++) {
+ memcpy(dest, map, bytesPerRow);
+ map += tex_xfer->stride;
+ dest += destStride;
+ }
}
}