/* Upload data for a particular image. */ void st_texture_image_data(struct st_context *st, struct pipe_resource *dst, GLuint face, GLuint level, void *src, GLuint src_row_stride, GLuint src_image_stride) { struct pipe_context *pipe = st->pipe; GLuint i; const GLubyte *srcUB = src; GLuint layers; if (dst->target == PIPE_TEXTURE_1D_ARRAY || dst->target == PIPE_TEXTURE_2D_ARRAY || dst->target == PIPE_TEXTURE_CUBE_ARRAY) layers = dst->array_size; else layers = u_minify(dst->depth0, level); DBG("%s\n", __FUNCTION__); for (i = 0; i < layers; i++) { struct pipe_box box; u_box_2d_zslice(0, 0, face + i, u_minify(dst->width0, level), u_minify(dst->height0, level), &box); pipe->transfer_inline_write(pipe, dst, level, PIPE_TRANSFER_WRITE, &box, srcUB, src_row_stride, 0); srcUB += src_image_stride; } }
void renderer_copy_surface(struct renderer *ctx, struct pipe_surface *src, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, int dstX0, int dstY0, int dstX1, int dstY1, float z, unsigned filter) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_sampler_view view_templ; struct pipe_sampler_view *view; struct pipe_box src_box; struct pipe_resource texTemp, *tex; const struct pipe_framebuffer_state *fb = &ctx->g3d.fb; const int srcW = abs(srcX1 - srcX0); const int srcH = abs(srcY1 - srcY0); const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); if (srcLeft != srcX0) { /* left-right flip */ int tmp = dstX0; dstX0 = dstX1; dstX1 = tmp; } if (srcTop != srcY0) { /* up-down flip */ int tmp = dstY0; dstY0 = dstY1; dstY1 = tmp; } assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW)); assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW)); assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)); /* * XXX for now we're always creating a temporary texture. * Strictly speaking that's not always needed. */ /* create temp texture */ memset(&texTemp, 0, sizeof(texTemp)); texTemp.target = PIPE_TEXTURE_2D; texTemp.format = src->format; texTemp.last_level = 0; texTemp.width0 = srcW; texTemp.height0 = srcH; texTemp.depth0 = 1; texTemp.array_size = 1; texTemp.bind = PIPE_BIND_SAMPLER_VIEW; tex = screen->resource_create(screen, &texTemp); if (!tex) return; u_sampler_view_default_template(&view_templ, tex, tex->format); view = pipe->create_sampler_view(pipe, tex, &view_templ); if (!view) return; u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box); pipe->resource_copy_region(pipe, tex, 0, 0, 0, 0, /* dest */ src->texture, 0, &src_box); assert(floatsEqual(z, 0.0f)); /* draw */ if (fb->cbufs[0] == dst) { /* transform back to surface coordinates */ dstY0 = dst->height - dstY0; dstY1 = dst->height - dstY1; if (renderer_drawtex_begin(ctx, view)) { renderer_drawtex(ctx, dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, 0, 0, view->texture->width0, view->texture->height0); renderer_drawtex_end(ctx); } } else { if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) { renderer_copy(ctx, dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, 0, 0, view->texture->width0, view->texture->height0); renderer_copy_end(ctx); } } }
/** * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible. * Note that the region to copy has already been clipped so we know we * won't read from outside the source renderbuffer's bounds. * * Note: srcY=0=Bottom of renderbuffer (GL convention) */ static void st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage, GLint destX, GLint destY, GLint destZ, struct gl_renderbuffer *rb, GLint srcX, GLint srcY, GLsizei width, GLsizei height) { struct st_texture_image *stImage = st_texture_image(texImage); const GLenum texBaseFormat = texImage->_BaseFormat; struct st_renderbuffer *strb = st_renderbuffer(rb); struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; enum pipe_format dest_format, src_format; GLboolean matching_base_formats; GLuint color_writemask, zs_writemask, sample_count; struct pipe_surface *dest_surface = NULL; GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP); struct pipe_surface surf_tmpl; unsigned int dst_usage; GLint srcY0, srcY1; /* make sure finalize_textures has been called? */ if (0) st_validate_state(st); if (!strb || !strb->surface || !stImage->pt) { debug_printf("%s: null strb or stImage\n", __FUNCTION__); return; } sample_count = strb->surface->texture->nr_samples; /* I believe this would be legal, presumably would need to do a resolve for color, and for depth/stencil spec says to just use one of the depth/stencil samples per pixel? Need some transfer clarifications. */ assert(sample_count < 2); assert(strb); assert(strb->surface); assert(stImage->pt); src_format = strb->surface->format; dest_format = stImage->pt->format; /* * Determine if the src framebuffer and dest texture have the same * base format. We need this to detect a case such as the framebuffer * being GL_RGBA but the texture being GL_RGB. If the actual hardware * texture format stores RGBA we need to set A=1 (overriding the * framebuffer's alpha values). We can't do that with the blit or * textured-quad paths. */ matching_base_formats = (_mesa_get_format_base_format(strb->Base.Format) == _mesa_get_format_base_format(texImage->TexFormat)); if (ctx->_ImageTransferState) { goto fallback; } if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { /* 1D arrays might be thought of as 2D images but the actual layout * might not be that way. At some points, we convert OpenGL's 1D * array 'height' into gallium 'layers' and that prevents the blit * utility code from doing the right thing. Simpy use the memcpy-based * fallback. */ goto fallback; } if (matching_base_formats && src_format == dest_format && !do_flip) { /* use surface_copy() / blit */ struct pipe_box src_box; unsigned dstLevel; u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer, width, height, &src_box); /* If stImage->pt is an independent image (not a pointer into a full * mipmap) stImage->pt.last_level will be zero and we need to use that * as the dest level. */ dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level); /* for resource_copy_region(), y=0=top, always */ pipe->resource_copy_region(pipe, /* dest */ stImage->pt, dstLevel, destX, destY, destZ + stImage->base.Face, /* src */ strb->texture, strb->surface->u.tex.level, &src_box); return; } if (texBaseFormat == GL_DEPTH_STENCIL) { goto fallback; } if (texBaseFormat == GL_DEPTH_COMPONENT) { color_writemask = 0; zs_writemask = BLIT_WRITEMASK_Z; dst_usage = PIPE_BIND_DEPTH_STENCIL; } else { color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage); zs_writemask = 0; dst_usage = PIPE_BIND_RENDER_TARGET; } if ((!color_writemask && !zs_writemask) || !screen->is_format_supported(screen, src_format, PIPE_TEXTURE_2D, sample_count, PIPE_BIND_SAMPLER_VIEW) || !screen->is_format_supported(screen, dest_format, PIPE_TEXTURE_2D, 0, dst_usage)) { goto fallback; } if (do_flip) { srcY1 = strb->Base.Height - srcY - height; srcY0 = srcY1 + height; } else { srcY0 = srcY; srcY1 = srcY0 + height; } /* Disable conditional rendering. */ if (st->render_condition) { pipe->render_condition(pipe, NULL, 0); } memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = util_format_linear(stImage->pt->format); surf_tmpl.usage = dst_usage; surf_tmpl.u.tex.level = stImage->base.Level; surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ; surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ; dest_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl); util_blit_pixels(st->blit, strb->texture, strb->surface->u.tex.level, srcX, srcY0, srcX + width, srcY1, strb->surface->u.tex.first_layer, dest_surface, destX, destY, destX + width, destY + height, 0.0, PIPE_TEX_MIPFILTER_NEAREST, color_writemask, zs_writemask); pipe_surface_reference(&dest_surface, NULL); /* Restore conditional rendering state. */ if (st->render_condition) { pipe->render_condition(pipe, st->render_condition, st->condition_mode); } return; fallback: /* software fallback */ fallback_copy_texsubimage(ctx, strb, stImage, texBaseFormat, destX, destY, destZ, srcX, srcY, width, height); }
/* When this function is called, we have already checked * The copy regions fit the surfaces */ void NineSurface9_CopyMemToDefault( struct NineSurface9 *This, struct NineSurface9 *From, const POINT *pDestPoint, const RECT *pSourceRect ) { struct pipe_context *pipe = This->pipe; struct pipe_transfer *transfer = NULL; struct pipe_resource *r_dst = This->base.resource; struct pipe_box dst_box; uint8_t *map = NULL; int src_x, src_y, dst_x, dst_y, copy_width, copy_height; assert(This->base.pool == D3DPOOL_DEFAULT && From->base.pool == D3DPOOL_SYSTEMMEM); if (pDestPoint) { dst_x = pDestPoint->x; dst_y = pDestPoint->y; } else { dst_x = 0; dst_y = 0; } if (pSourceRect) { src_x = pSourceRect->left; src_y = pSourceRect->top; copy_width = pSourceRect->right - pSourceRect->left; copy_height = pSourceRect->bottom - pSourceRect->top; } else { src_x = 0; src_y = 0; copy_width = From->desc.Width; copy_height = From->desc.Height; } u_box_2d_zslice(dst_x, dst_y, This->layer, copy_width, copy_height, &dst_box); map = pipe->transfer_map(pipe, r_dst, This->level, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, &dst_box, &transfer); if (!map) return; /* Note: if formats are the sames, it will revert * to normal memcpy */ (void) util_format_translate(r_dst->format, map, transfer->stride, 0, 0, From->base.info.format, From->data, From->stride, src_x, src_y, copy_width, copy_height); pipe_transfer_unmap(pipe, transfer); if (This->data_conversion) (void) util_format_translate(This->format_conversion, This->data_conversion, This->stride_conversion, dst_x, dst_y, From->base.info.format, From->data, From->stride, src_x, src_y, copy_width, copy_height); NineSurface9_MarkContainerDirty(This); }
/** * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible. * Note that the region to copy has already been clipped so we know we * won't read from outside the source renderbuffer's bounds. * * Note: srcY=0=Bottom of renderbuffer (GL convention) */ static void st_copy_texsubimage(struct gl_context *ctx, struct gl_texture_image *texImage, GLint destX, GLint destY, GLint destZ, struct gl_renderbuffer *rb, GLint srcX, GLint srcY, GLsizei width, GLsizei height) { struct st_texture_image *stImage = st_texture_image(texImage); const GLenum texBaseFormat = texImage->_BaseFormat; struct gl_framebuffer *fb = ctx->ReadBuffer; struct st_renderbuffer *strb; struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; enum pipe_format dest_format, src_format; GLboolean matching_base_formats; GLuint format_writemask, sample_count; struct pipe_surface *dest_surface = NULL; GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP); struct pipe_surface surf_tmpl; unsigned int dst_usage; GLint srcY0, srcY1; /* make sure finalize_textures has been called? */ if (0) st_validate_state(st); /* determine if copying depth or color data */ if (texBaseFormat == GL_DEPTH_COMPONENT || texBaseFormat == GL_DEPTH_STENCIL) { strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); } else { /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */ strb = st_renderbuffer(fb->_ColorReadBuffer); } if (!strb || !strb->surface || !stImage->pt) { debug_printf("%s: null strb or stImage\n", __FUNCTION__); return; } sample_count = strb->surface->texture->nr_samples; /* I believe this would be legal, presumably would need to do a resolve for color, and for depth/stencil spec says to just use one of the depth/stencil samples per pixel? Need some transfer clarifications. */ assert(sample_count < 2); assert(strb); assert(strb->surface); assert(stImage->pt); src_format = strb->surface->format; dest_format = stImage->pt->format; /* * Determine if the src framebuffer and dest texture have the same * base format. We need this to detect a case such as the framebuffer * being GL_RGBA but the texture being GL_RGB. If the actual hardware * texture format stores RGBA we need to set A=1 (overriding the * framebuffer's alpha values). We can't do that with the blit or * textured-quad paths. */ matching_base_formats = (_mesa_get_format_base_format(strb->Base.Format) == _mesa_get_format_base_format(texImage->TexFormat)); if (ctx->_ImageTransferState) { goto fallback; } if (matching_base_formats && src_format == dest_format && !do_flip) { /* use surface_copy() / blit */ struct pipe_box src_box; u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer, width, height, &src_box); /* for resource_copy_region(), y=0=top, always */ pipe->resource_copy_region(pipe, /* dest */ stImage->pt, stImage->base.Level, destX, destY, destZ + stImage->base.Face, /* src */ strb->texture, strb->surface->u.tex.level, &src_box); return; } if (texBaseFormat == GL_DEPTH_STENCIL) { goto fallback; } if (texBaseFormat == GL_DEPTH_COMPONENT) { format_writemask = TGSI_WRITEMASK_XYZW; dst_usage = PIPE_BIND_DEPTH_STENCIL; } else { format_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage); dst_usage = PIPE_BIND_RENDER_TARGET; } if (!format_writemask || !screen->is_format_supported(screen, src_format, PIPE_TEXTURE_2D, sample_count, PIPE_BIND_SAMPLER_VIEW) || !screen->is_format_supported(screen, dest_format, PIPE_TEXTURE_2D, 0, dst_usage)) { goto fallback; } if (do_flip) { srcY1 = strb->Base.Height - srcY - height; srcY0 = srcY1 + height; } else { srcY0 = srcY; srcY1 = srcY0 + height; } /* Disable conditional rendering. */ if (st->render_condition) { pipe->render_condition(pipe, NULL, 0); } memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = util_format_linear(stImage->pt->format); surf_tmpl.usage = dst_usage; surf_tmpl.u.tex.level = stImage->base.Level; surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ; surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ; dest_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl); util_blit_pixels_writemask(st->blit, strb->texture, strb->surface->u.tex.level, srcX, srcY0, srcX + width, srcY1, strb->surface->u.tex.first_layer, dest_surface, destX, destY, destX + width, destY + height, 0.0, PIPE_TEX_MIPFILTER_NEAREST, format_writemask); pipe_surface_reference(&dest_surface, NULL); /* Restore conditional rendering state. */ if (st->render_condition) { pipe->render_condition(pipe, st->render_condition, st->condition_mode); } return; fallback: /* software fallback */ fallback_copy_texsubimage(ctx, strb, stImage, texBaseFormat, destX, destY, destZ, srcX, srcY, width, height); }