void debug_dump_transfer_bmp(const char *filename, struct pipe_transfer *transfer) { #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT float *rgba; if (!transfer) goto error1; rgba = MALLOC(transfer->width*transfer->height*4*sizeof(float)); if(!rgba) goto error1; pipe_get_tile_rgba(transfer, 0, 0, transfer->width, transfer->height, rgba); debug_dump_float_rgba_bmp(filename, transfer->width, transfer->height, rgba, transfer->width); FREE(rgba); error1: ; #endif }
void debug_dump_transfer_bmp(struct pipe_context *pipe, const char *filename, struct pipe_transfer *transfer, void *ptr) { float *rgba; if (!transfer) goto error1; rgba = MALLOC(transfer->box.width * transfer->box.height * transfer->box.depth * 4*sizeof(float)); if(!rgba) goto error1; pipe_get_tile_rgba(transfer, ptr, 0, 0, transfer->box.width, transfer->box.height, rgba); debug_dump_float_rgba_bmp(filename, transfer->box.width, transfer->box.height, rgba, transfer->box.width); FREE(rgba); error1: ; }
/** * Probe and test if the rectangle contains the expected color. * * If "num_expected_colors" > 1, at least one expected color must match * the probed color. "expected" should be an array of 4*num_expected_colors * floats. */ static bool util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex, unsigned offx, unsigned offy, unsigned w, unsigned h, const float *expected, unsigned num_expected_colors) { struct pipe_transfer *transfer; void *map; float *pixels = malloc(w * h * 4 * sizeof(float)); int x,y,e,c; bool pass = true; map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ, offx, offy, w, h, &transfer); pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels); pipe_transfer_unmap(ctx, transfer); for (e = 0; e < num_expected_colors; e++) { for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { float *probe = &pixels[(y*w + x)*4]; for (c = 0; c < 4; c++) { if (fabs(probe[c] - expected[e*4+c]) >= TOLERANCE) { if (e < num_expected_colors-1) goto next_color; /* test the next expected color */ printf("Probe color at (%i,%i), ", offx+x, offy+y); printf("Expected: %.3f, %.3f, %.3f, %.3f, ", expected[e*4], expected[e*4+1], expected[e*4+2], expected[e*4+3]); printf("Got: %.3f, %.3f, %.3f, %.3f\n", probe[0], probe[1], probe[2], probe[2]); pass = false; goto done; } } } } break; /* this color was successful */ next_color:; } done: free(pixels); return pass; }
static void accum_load(struct st_context *st, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, struct st_renderbuffer *acc_strb, struct st_renderbuffer *color_strb) { struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_transfer *color_trans; size_t stride = acc_strb->stride; GLubyte *data = acc_strb->data; GLfloat *buf; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture, 0, 0, 0, PIPE_TRANSFER_READ, xpos, ypos, width, height); buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: { const GLfloat *color = buf; int i, j; for (i = 0; i < height; i++) { GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); for (j = 0; j < width * 4; j++) { float val = *color++ * value; *acc++ = FLOAT_TO_SHORT(val); } } } break; default: _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } _mesa_free(buf); screen->tex_transfer_destroy(color_trans); }
void image_get_sub_data(struct vg_image * image, void * data, VGint dataStride, VGImageFormat dataFormat, VGint sx, VGint sy, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; VGfloat *df = (VGfloat*)temp; VGint y = 0, yStep = 1; VGint i; VGubyte *dst = (VGubyte *)data; { struct pipe_transfer *transfer = screen->get_tex_transfer(screen, image->texture, 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, image->x + image->width, image->y + image->height); /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { #if 0 debug_printf("%d-%d == %d\n", sy, height, y); #endif pipe_get_tile_rgba(transfer, sx+image->x, y, width, 1, df); y += yStep; _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst); dst += dataStride; } screen->tex_transfer_destroy(transfer); } }
void vgReadPixels(void * data, VGint dataStride, VGImageFormat dataFormat, VGint sx, VGint sy, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct st_framebuffer *stfb = ctx->draw_buffer; struct st_renderbuffer *strb = stfb->strb; struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; VGfloat *df = (VGfloat*)temp; VGint y = (fb->height - sy) - 1, yStep = -1; VGint i; VGubyte *dst = (VGubyte *)data; VGint xoffset = 0, yoffset = 0; if (!supported_image_format(dataFormat)) { vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); return; } if (!data || !is_aligned(data)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } if (width <= 0 || height <= 0) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } /* make sure rendering has completed */ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); if (sx < 0) { xoffset = -sx; xoffset *= _vega_size_for_format(dataFormat); width += sx; sx = 0; } if (sy < 0) { yoffset = -sy; height += sy; sy = 0; y = (fb->height - sy) - 1; yoffset *= dataStride; } { struct pipe_transfer *transfer; transfer = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, width, height); /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { #if 0 debug_printf("%d-%d == %d\n", sy, height, y); #endif pipe_get_tile_rgba(transfer, sx, y, width, 1, df); y += yStep; _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst + yoffset + xoffset); dst += dataStride; } screen->tex_transfer_destroy(transfer); } }
static void accum_return(GLcontext *ctx, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, struct st_renderbuffer *acc_strb, struct st_renderbuffer *color_strb) { struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; const GLubyte *colormask = ctx->Color.ColorMask; enum pipe_transfer_usage usage; struct pipe_transfer *color_trans; size_t stride = acc_strb->stride; const GLubyte *data = acc_strb->data; GLfloat *buf; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) usage = PIPE_TRANSFER_READ_WRITE; else usage = PIPE_TRANSFER_WRITE; color_trans = st_cond_flush_get_tex_transfer(st_context(ctx), color_strb->texture, 0, 0, 0, usage, xpos, ypos, width, height); if (usage & PIPE_TRANSFER_READ) pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: { GLfloat *color = buf; int i, j, ch; for (i = 0; i < height; i++) { const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8); for (j = 0; j < width; j++) { for (ch = 0; ch < 4; ch++) { if (colormask[ch]) { GLfloat val = SHORT_TO_FLOAT(*acc * value); *color = CLAMP(val, 0.0f, 1.0f); } else { /* No change */ } ++acc; ++color; } } } } break; default: _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } pipe_put_tile_rgba(color_trans, 0, 0, width, height, buf); _mesa_free(buf); screen->tex_transfer_destroy(color_trans); }
/** * Get a tile from the cache. * \param x, y position of tile, in pixels */ struct softpipe_cached_tile * sp_find_cached_tile(struct softpipe_tile_cache *tc, union tile_address addr ) { struct pipe_transfer *pt = tc->transfer; /* cache pos/entry: */ const int pos = CACHE_POS(addr.bits.x, addr.bits.y); struct softpipe_cached_tile *tile = tc->entries + pos; if (addr.value != tile->addr.value) { assert(pt->resource); if (tile->addr.bits.invalid == 0) { /* put dirty tile back in framebuffer */ if (tc->depth_stencil) { pipe_put_tile_raw(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { pipe_put_tile_rgba(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, (float *) tile->data.color); } } tile->addr = addr; if (is_clear_flag_set(tc->clear_flags, addr)) { /* don't get tile from framebuffer, just clear it */ if (tc->depth_stencil) { clear_tile(tile, pt->resource->format, tc->clear_val); } else { clear_tile_rgba(tile, pt->resource->format, tc->clear_color); } clear_clear_flag(tc->clear_flags, addr); } else { /* get new tile data from transfer */ if (tc->depth_stencil) { pipe_get_tile_raw(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { pipe_get_tile_rgba(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, (float *) tile->data.color); } } } tc->last_tile = tile; return tile; }
void vegaReadPixels(void * data, VGint dataStride, VGImageFormat dataFormat, VGint sx, VGint sy, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; struct st_framebuffer *stfb = ctx->draw_buffer; struct st_renderbuffer *strb = stfb->strb; VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; VGfloat *df = (VGfloat*)temp; VGint i; VGubyte *dst = (VGubyte *)data; VGint xoffset = 0, yoffset = 0; if (!supported_image_format(dataFormat)) { vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); return; } if (!data || !is_aligned(data)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } if (width <= 0 || height <= 0) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } if (sx < 0) { xoffset = -sx; xoffset *= _vega_size_for_format(dataFormat); width += sx; sx = 0; } if (sy < 0) { yoffset = -sy; yoffset *= dataStride; height += sy; sy = 0; } if (sx + width > stfb->width || sy + height > stfb->height) { width = stfb->width - sx; height = stfb->height - sy; /* nothing to read */ if (width <= 0 || height <= 0) return; } { VGint y = (stfb->height - sy) - 1, yStep = -1; struct pipe_transfer *transfer; void *map; map = pipe_transfer_map(pipe, strb->texture, 0, 0, PIPE_TRANSFER_READ, 0, 0, sx + width, stfb->height - sy, &transfer); /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { #if 0 debug_printf("%d-%d == %d\n", sy, height, y); #endif pipe_get_tile_rgba(transfer, map, sx, y, width, 1, df); y += yStep; _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst + yoffset + xoffset); dst += dataStride; } pipe->transfer_unmap(pipe, transfer); } }
void debug_dump_surface_bmp(const char *filename, struct pipe_surface *surface) { struct util_stream *stream; unsigned surface_usage; struct bmp_file_header bmfh; struct bmp_info_header bmih; float *rgba; unsigned x, y; if (!surface) goto error1; rgba = MALLOC(surface->width*4*sizeof(float)); if(!rgba) goto error1; bmfh.bfType = 0x4d42; bmfh.bfSize = 14 + 40 + surface->height*surface->width*4; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = 14 + 40; bmih.biSize = 40; bmih.biWidth = surface->width; bmih.biHeight = surface->height; bmih.biPlanes = 1; bmih.biBitCount = 32; bmih.biCompression = 0; bmih.biSizeImage = surface->height*surface->width*4; bmih.biXPelsPerMeter = 0; bmih.biYPelsPerMeter = 0; bmih.biClrUsed = 0; bmih.biClrImportant = 0; stream = util_stream_create(filename, bmfh.bfSize); if(!stream) goto error2; util_stream_write(stream, &bmfh, 14); util_stream_write(stream, &bmih, 40); /* XXX: force mappable surface */ surface_usage = surface->usage; surface->usage |= PIPE_BUFFER_USAGE_CPU_READ; y = surface->height; while(y--) { pipe_get_tile_rgba(surface, 0, y, surface->width, 1, rgba); for(x = 0; x < surface->width; ++x) { struct bmp_rgb_quad pixel; pixel.rgbRed = float_to_ubyte(rgba[x*4 + 0]); pixel.rgbGreen = float_to_ubyte(rgba[x*4 + 1]); pixel.rgbBlue = float_to_ubyte(rgba[x*4 + 2]); pixel.rgbAlpha = float_to_ubyte(rgba[x*4 + 3]); util_stream_write(stream, &pixel, 4); } } surface->usage = surface_usage; util_stream_close(stream); error2: FREE(rgba); error1: ; }
static void st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type) { struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *rbRead; struct st_vertex_program *stvp; struct st_fragment_program *stfp; struct pipe_texture *pt; GLfloat *color; enum pipe_format srcFormat, texFormat; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); st_validate_state(st); if (srcx < 0) { width -= -srcx; dstx += -srcx; srcx = 0; } if (srcy < 0) { height -= -srcy; dsty += -srcy; srcy = 0; } if (dstx < 0) { width -= -dstx; srcx += -dstx; dstx = 0; } if (dsty < 0) { height -= -dsty; srcy += -dsty; dsty = 0; } if (width < 0 || height < 0) return; if (type == GL_STENCIL) { /* can't use texturing to do stencil */ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); return; } if (type == GL_COLOR) { rbRead = st_get_color_read_renderbuffer(ctx); color = NULL; stfp = combined_drawpix_fragment_program(ctx); stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE); } else { assert(type == GL_DEPTH); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; stfp = make_fragment_shader_z(ctx->st); stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); } srcFormat = rbRead->texture->format; if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, 0)) { texFormat = srcFormat; } else { /* srcFormat can't be used as a texture format */ if (type == GL_DEPTH) { texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL); assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */ } else { /* default color format */ texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER); assert(texFormat != PIPE_FORMAT_NONE); } } if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { srcy = ctx->DrawBuffer->Height - srcy - height; if (srcy < 0) { height -= -srcy; srcy = 0; } if (height < 0) return; } pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0, width, height, 1, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) return; if (srcFormat == texFormat) { /* copy source framebuffer surface into mipmap/texture */ struct pipe_surface *psRead = screen->get_tex_surface(screen, rbRead->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); pipe->surface_copy(pipe, psTex, /* dest */ 0, 0, /* destx/y */ psRead, srcx, srcy, width, height); pipe_surface_reference(&psRead, NULL); pipe_surface_reference(&psTex, NULL); } else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, PIPE_TRANSFER_READ, srcx, srcy, width, height); struct pipe_transfer *ptTex; enum pipe_transfer_usage transfer_usage; if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; else transfer_usage = PIPE_TRANSFER_WRITE; ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage, 0, 0, width, height); if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); pipe_get_tile_rgba(ptRead, 0, 0, width, height, buf); pipe_put_tile_rgba(ptTex, 0, 0, width, height, buf); _mesa_free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint)); pipe_get_tile_z(ptRead, 0, 0, width, height, buf); pipe_put_tile_z(ptTex, 0, 0, width, height, buf); _mesa_free(buf); } screen->tex_transfer_destroy(ptRead); screen->tex_transfer_destroy(ptTex); } /* draw textured quad */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, pt, stvp, stfp, color, GL_TRUE); pipe_texture_reference(&pt, NULL); }