Path: blob/21.2-virgl/src/gallium/drivers/svga/svga_pipe_blit.c
4570 views
/**********************************************************1* Copyright 2008-2017 VMware, Inc. All rights reserved.2*3* Permission is hereby granted, free of charge, to any person4* obtaining a copy of this software and associated documentation5* files (the "Software"), to deal in the Software without6* restriction, including without limitation the rights to use, copy,7* modify, merge, publish, distribute, sublicense, and/or sell copies8* of the Software, and to permit persons to whom the Software is9* furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23**********************************************************/2425#include "svga_context.h"26#include "svga_debug.h"27#include "svga_cmd.h"28#include "svga_format.h"29#include "svga_resource_buffer.h"30#include "svga_resource_texture.h"31#include "svga_surface.h"3233//#include "util/u_blit_sw.h"34#include "util/format/u_format.h"35#include "util/u_surface.h"3637#define FILE_DEBUG_FLAG DEBUG_BLIT383940/**41* Build a struct pipe_blit_info object from the arguments used by the42* pipe::resource_copy_region() function.43*/44static void45build_blit_info(struct pipe_resource *dst_tex,46unsigned dst_level,47unsigned dst_x,48unsigned dst_y,49unsigned dst_z,50struct pipe_resource *src_tex,51unsigned src_level,52const struct pipe_box *src_box,53struct pipe_blit_info *blit)54{55memset(blit, 0, sizeof(*blit));5657blit->src.format = src_tex->format;58blit->dst.format = dst_tex->format;5960blit->mask = util_format_get_mask(blit->dst.format);61blit->filter = PIPE_TEX_FILTER_NEAREST;62blit->src.resource = src_tex;63blit->src.level = src_level;64blit->dst.resource = dst_tex;65blit->dst.level = dst_level;66blit->src.box = *src_box;67u_box_3d(dst_x, dst_y, dst_z, src_box->width, src_box->height,68src_box->depth, &blit->dst.box);69}7071/**72* Copy when src texture and dst texture are same with IntraSurfaceCopy73* command.74*/75static void76intra_surface_copy(struct svga_context *svga, struct pipe_resource *tex,77unsigned src_x, unsigned src_y, unsigned src_z,78unsigned level, unsigned layer_face,79unsigned dst_x, unsigned dst_y, unsigned dst_z,80unsigned width, unsigned height, unsigned depth)81{82SVGA3dCopyBox box;83struct svga_texture *stex;8485/*86* Makes sure we have flushed all buffered draw operations and also87* synchronizes all surfaces with any emulated surface views.88*/89svga_surfaces_flush(svga);9091stex = svga_texture(tex);9293box.x = dst_x;94box.y = dst_y;95box.z = dst_z;96box.w = width;97box.h = height;98box.d = depth;99box.srcx = src_x;100box.srcy = src_y;101box.srcz = src_z;102103SVGA_RETRY(svga, SVGA3D_vgpu10_IntraSurfaceCopy(svga->swc, stex->handle,104level, layer_face, &box));105/* Mark the texture subresource as rendered-to. */106svga_set_texture_rendered_to(stex, layer_face, level);107}108109/**110* Copy an image between textures with the vgpu10 CopyRegion command.111*/112static void113copy_region_vgpu10(struct svga_context *svga, struct pipe_resource *src_tex,114unsigned src_x, unsigned src_y, unsigned src_z,115unsigned src_level, unsigned src_layer_face,116struct pipe_resource *dst_tex,117unsigned dst_x, unsigned dst_y, unsigned dst_z,118unsigned dst_level, unsigned dst_layer_face,119unsigned width, unsigned height, unsigned depth)120{121uint32 srcSubResource, dstSubResource;122struct svga_texture *dtex, *stex;123124stex = svga_texture(src_tex);125dtex = svga_texture(dst_tex);126127svga_surfaces_flush(svga);128129srcSubResource = src_layer_face * (src_tex->last_level + 1) + src_level;130dstSubResource = dst_layer_face * (dst_tex->last_level + 1) + dst_level;131132svga_texture_copy_region(svga, stex->handle, srcSubResource,133src_x, src_y, src_z,134dtex->handle, dstSubResource,135dst_x, dst_y, dst_z,136width, height, depth);137138/* Mark the texture subresource as defined. */139svga_define_texture_level(dtex, dst_layer_face, dst_level);140141/* Mark the texture subresource as rendered-to. */142svga_set_texture_rendered_to(dtex, dst_layer_face, dst_level);143}144145146/**147* Fallback to the copy region utility which uses map/memcpy for the copy148*/149static void150copy_region_fallback(struct svga_context *svga,151struct pipe_resource *dst_tex, unsigned dst_level,152unsigned dstx, unsigned dsty, unsigned dstz,153struct pipe_resource *src_tex, unsigned src_level,154const struct pipe_box *src_box)155{156struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;157158SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_COPYREGIONFALLBACK);159util_resource_copy_region(&svga->pipe, dst_tex, dst_level, dstx,160dsty, dstz, src_tex, src_level, src_box);161SVGA_STATS_TIME_POP(sws);162(void) sws;163}164165166/**167* Whether the layer_face index is given by the Z coordinate.168*/169static bool170has_layer_face_index_in_z(enum pipe_texture_target target)171{172if (target == PIPE_TEXTURE_CUBE ||173target == PIPE_TEXTURE_1D_ARRAY ||174target == PIPE_TEXTURE_2D_ARRAY ||175target == PIPE_TEXTURE_CUBE_ARRAY)176return true;177else178return false;179}180181182/**183* For some texture types, we need to move the z (slice) coordinate184* to the layer value. For example, to select the z=3 slice of a 2D ARRAY185* texture, we need to use layer=3 and set z=0.186*/187static void188adjust_z_layer(enum pipe_texture_target target,189int z_in, unsigned *layer_out, unsigned *z_out)190{191if (target == PIPE_TEXTURE_CUBE ||192target == PIPE_TEXTURE_1D_ARRAY ||193target == PIPE_TEXTURE_2D_ARRAY ||194target == PIPE_TEXTURE_CUBE_ARRAY) {195*layer_out = z_in;196*z_out = 0;197}198else {199*layer_out = 0;200*z_out = z_in;201}202}203204205/**206* Are the given SVGA3D formats compatible, in terms of vgpu10's207* PredCopyRegion() command?208*/209static bool210formats_compatible(const struct svga_screen *ss,211SVGA3dSurfaceFormat src_svga_fmt,212SVGA3dSurfaceFormat dst_svga_fmt)213{214src_svga_fmt = svga_typeless_format(src_svga_fmt);215dst_svga_fmt = svga_typeless_format(dst_svga_fmt);216217return src_svga_fmt == dst_svga_fmt;218}219220221/**222* Check whether the blending is enabled or not223*/224static bool225is_blending_enabled(struct svga_context *svga,226const struct pipe_blit_info *blit)227{228bool blend_enable = false;229int i;230if (svga->curr.blend) {231if (svga->curr.blend->independent_blend_enable) {232for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {233struct pipe_surface *cbuf = svga->curr.framebuffer.cbufs[i];234if (cbuf && (cbuf->texture == blit->dst.resource)) {235if (svga->curr.blend->rt[i].blend_enable) {236blend_enable = true;237}238break;239}240}241}242else {243if (svga->curr.blend->rt[0].blend_enable)244blend_enable = true;245}246}247return blend_enable;248}249250/**251* If GL_FRAMEBUFFER_SRGB is enabled, then output colorspace is252* expected to be sRGB if blending is not enabled.253* If GL_FRAMEBUFFER_SRGB is disabled, then we can use254* copy_region_vgpu10()255* Following table basically tells when copy_region_vgpu10 can be256* used if GL_FRAMEBUFFER_SRGB is enabled.257* ______________________________________________________________258* | src fmt | dst_fmt | blending |Can use |259* | | | |copy_region |260* ______________________________________________________________261* | linear | linear | N | Y |262* | linear | linear | Y | Y |263* | linear | sRGB | N | N |264* | linear | sRGB | Y | Y |265* | sRGB | linear | N | N |266* | sRGB | linear | Y | N |267* | sRGB | sRGB | N | Y |268* | sRGB | sRGB | Y | N |269* ______________________________________________________________270*271*/272static bool273check_blending_and_srgb_cond(struct svga_context *svga,274const struct pipe_blit_info *blit)275{276enum pipe_format sFmt = blit->src.format;277enum pipe_format dFmt = blit->dst.format;278279if (is_blending_enabled(svga, blit)) {280if (!util_format_is_srgb(blit->src.format))281return true;282}283else {284if (util_format_is_srgb(sFmt) && util_format_is_srgb(dFmt))285return true;286else if (!util_format_is_srgb(sFmt)){287if (!util_format_is_srgb(dFmt))288return true;289else {290/**291* State tracker converts all sRGB src blit format292* to linear if GL_FRAMEBUFFER_SRGB is disabled.293* So if src resource format is sRGB and294* blit format is linear then it means,295* GL_FRAMEBUFFER_SRGB is disabled. In this case also296* we can use copy_region_vgpu10().297*/298299if (util_format_is_srgb(blit->src.resource->format))300return true;301}302}303}304return false;305}306307/**308* Do common checks for svga surface copy.309*/310static bool311can_blit_via_svga_copy_region(struct svga_context *svga,312const struct pipe_blit_info *blit_info)313{314struct pipe_blit_info local_blit = *blit_info;315316/* First basic checks to catch incompatibilities in new or locally unchecked317* struct pipe_blit_info members but bypass the format check here.318* Also since util_can_blit_via_copy_region() requires a dimension match,319* PIPE_FILTER_LINEAR should be equal to PIPE_FILTER_NEAREST.320*/321local_blit.dst.format = local_blit.src.format;322if (local_blit.filter == PIPE_TEX_FILTER_LINEAR)323local_blit.filter = PIPE_TEX_FILTER_NEAREST;324if (!util_can_blit_via_copy_region(&local_blit, TRUE))325return false;326327/* For depth+stencil formats, copy with mask != PIPE_MASK_ZS is not328* supported329*/330if (util_format_is_depth_and_stencil(blit_info->src.format) &&331blit_info->mask != (PIPE_MASK_ZS))332return false;333334return check_blending_and_srgb_cond(svga, blit_info);335}336337/**338* Check whether we can blit using the intra_surface_copy command.339*/340static bool341can_blit_via_intra_surface_copy(struct svga_context *svga,342const struct pipe_blit_info *blit_info)343{344struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;345struct svga_texture *dtex, *stex;346347if (!svga_have_vgpu10(svga))348return false;349350/* src surface cannot be multisample */351if (blit_info->src.resource->nr_samples > 1)352return false;353354if (!sws->have_intra_surface_copy)355return false;356357if (svga->render_condition && blit_info->render_condition_enable)358return false;359360if (blit_info->src.level != blit_info->dst.level)361return false;362363if (has_layer_face_index_in_z(blit_info->src.resource->target)){364if (blit_info->src.box.z != blit_info->dst.box.z)365return false;366}367368stex = svga_texture(blit_info->src.resource);369dtex = svga_texture(blit_info->dst.resource);370371return (stex->handle == dtex->handle);372}373374375/**376* the gallium frontend implements some resource copies with blits (for377* GL_ARB_copy_image). This function checks if we should really do the blit378* with a VGPU10 CopyRegion command or software fallback (for incompatible379* src/dst formats).380*/381static bool382can_blit_via_copy_region_vgpu10(struct svga_context *svga,383const struct pipe_blit_info *blit_info)384{385struct svga_texture *dtex, *stex;386387/* can't copy between different resource types */388if (svga_resource_type(blit_info->src.resource->target) !=389svga_resource_type(blit_info->dst.resource->target))390return false;391392stex = svga_texture(blit_info->src.resource);393dtex = svga_texture(blit_info->dst.resource);394395if (!svga_have_vgpu10(svga))396return false;397398if (stex->handle == dtex->handle)399return false;400401return formats_compatible(svga_screen(svga->pipe.screen),402stex->key.format,403dtex->key.format);404}405406407/**408* Check whether we can blit using the surface_copy command.409*/410static bool411can_blit_via_surface_copy(struct svga_context *svga,412const struct pipe_blit_info *blit_info)413{414struct svga_texture *dtex, *stex;415416/* Mimic the format tests in util_can_blit_via_copy_region(), but417* skip the other tests that have already been performed.418*/419if (blit_info->src.format != blit_info->dst.format) {420const struct util_format_description *src_desc, *dst_desc;421422src_desc = util_format_description(blit_info->src.resource->format);423dst_desc = util_format_description(blit_info->dst.resource->format);424425if (blit_info->src.resource->format != blit_info->src.format ||426blit_info->dst.resource->format != blit_info->dst.format ||427!util_is_format_compatible(src_desc, dst_desc))428return false;429}430431if (svga->render_condition && blit_info->render_condition_enable)432return false;433434/* can't copy between different resource types */435if (svga_resource_type(blit_info->src.resource->target) !=436svga_resource_type(blit_info->dst.resource->target))437return false;438439stex = svga_texture(blit_info->src.resource);440dtex = svga_texture(blit_info->dst.resource);441442if (stex->handle == dtex->handle)443return false;444445/*446* This is what we've been using before, but it can probably be447* relaxed. The device checks are less stringent.448*/449return (stex->b.format == dtex->b.format);450}451452453/**454* Try region copy using one of the region copy commands455*/456static bool457try_copy_region(struct svga_context *svga,458const struct pipe_blit_info *blit)459{460unsigned src_layer_face, src_z, dst_layer_face, dst_z;461462if (!can_blit_via_svga_copy_region(svga, blit))463return false;464465adjust_z_layer(blit->src.resource->target, blit->src.box.z,466&src_layer_face, &src_z);467468adjust_z_layer(blit->dst.resource->target, blit->dst.box.z,469&dst_layer_face, &dst_z);470471if (can_blit_via_copy_region_vgpu10(svga, blit)) {472svga_toggle_render_condition(svga, blit->render_condition_enable, FALSE);473474copy_region_vgpu10(svga,475blit->src.resource,476blit->src.box.x, blit->src.box.y, src_z,477blit->src.level, src_layer_face,478blit->dst.resource,479blit->dst.box.x, blit->dst.box.y, dst_z,480blit->dst.level, dst_layer_face,481blit->src.box.width, blit->src.box.height,482blit->src.box.depth);483484svga_toggle_render_condition(svga, blit->render_condition_enable, TRUE);485486return true;487}488489if (can_blit_via_surface_copy(svga, blit)) {490struct svga_texture *stex = svga_texture(blit->src.resource);491struct svga_texture *dtex = svga_texture(blit->dst.resource);492493svga_surfaces_flush(svga);494495svga_texture_copy_handle(svga,496stex->handle,497blit->src.box.x, blit->src.box.y, src_z,498blit->src.level, src_layer_face,499dtex->handle,500blit->dst.box.x, blit->dst.box.y, dst_z,501blit->dst.level, dst_layer_face,502blit->src.box.width, blit->src.box.height,503blit->src.box.depth);504505svga_define_texture_level(dtex, dst_layer_face, blit->dst.level);506svga_set_texture_rendered_to(dtex, dst_layer_face, blit->dst.level);507return true;508}509510if (can_blit_via_intra_surface_copy(svga, blit)) {511intra_surface_copy(svga,512blit->src.resource,513blit->src.box.x, blit->src.box.y, src_z,514blit->src.level, src_layer_face,515blit->dst.box.x, blit->dst.box.y, dst_z,516blit->src.box.width, blit->src.box.height,517blit->src.box.depth);518return true;519}520521return false;522}523524525/**526* A helper function to determine if the specified view format527* is compatible with the surface format.528* It is compatible if the view format is the same as the surface format,529* or the associated svga format for the surface is a typeless format, or530* the view format is an adjusted format for BGRX/BGRA resource.531*/532static bool533is_view_format_compatible(enum pipe_format surf_fmt,534SVGA3dSurfaceFormat surf_svga_fmt,535enum pipe_format view_fmt)536{537if (surf_fmt == view_fmt || svga_format_is_typeless(surf_svga_fmt))538return true;539540if ((surf_fmt == PIPE_FORMAT_B8G8R8X8_UNORM &&541view_fmt == PIPE_FORMAT_B8G8R8A8_UNORM) ||542(surf_fmt == PIPE_FORMAT_B8G8R8A8_UNORM &&543view_fmt == PIPE_FORMAT_B8G8R8X8_UNORM))544return true;545546return false;547}548549550/**551* Try issuing a quad blit.552*/553static bool554try_blit(struct svga_context *svga, const struct pipe_blit_info *blit_info)555{556struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;557struct pipe_resource *src = blit_info->src.resource;558struct pipe_resource *dst = blit_info->dst.resource;559struct pipe_resource *newSrc = NULL;560struct pipe_resource *newDst = NULL;561bool can_create_src_view;562bool can_create_dst_view;563bool ret = true;564struct pipe_blit_info blit = *blit_info;565566SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_BLITBLITTER);567568/**569* Avoid using util_blitter_blit() for these depth formats on non-vgpu10570* devices because these depth formats only support comparison mode571* and not ordinary sampling.572*/573if (!svga_have_vgpu10(svga) && (blit.mask & PIPE_MASK_Z) &&574(svga_texture(dst)->key.format == SVGA3D_Z_D16 ||575svga_texture(dst)->key.format == SVGA3D_Z_D24X8 ||576svga_texture(dst)->key.format == SVGA3D_Z_D24S8)) {577ret = false;578goto done;579}580581/**582* If format is srgb and blend is enabled then color values need583* to be converted into linear format.584*/585if (is_blending_enabled(svga, &blit)) {586blit.src.format = util_format_linear(blit.src.format);587blit.dst.format = util_format_linear(blit.dst.format);588}589590/* Check if we can create shader resource view and591* render target view for the quad blitter to work592*/593can_create_src_view =594is_view_format_compatible(src->format, svga_texture(src)->key.format,595blit.src.format);596597can_create_dst_view =598is_view_format_compatible(dst->format, svga_texture(dst)->key.format,599blit.dst.format);600601if ((blit.mask & PIPE_MASK_S) ||602((!can_create_dst_view || !can_create_src_view)603&& !svga_have_vgpu10(svga))) {604/* Can't do stencil blits with textured quad blitter */605debug_warn_once("using software stencil blit");606ret = false;607goto done;608}609610if (!util_blitter_is_blit_supported(svga->blitter, &blit)) {611debug_printf("svga: blit unsupported %s -> %s\n",612util_format_short_name(blit.src.resource->format),613util_format_short_name(blit.dst.resource->format));614ret = false;615goto done;616}617618/* XXX turn off occlusion and streamout queries */619620util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb);621util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);622util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);623util_blitter_save_geometry_shader(svga->blitter, svga->curr.user_gs);624util_blitter_save_tessctrl_shader(svga->blitter, svga->curr.tcs);625util_blitter_save_tesseval_shader(svga->blitter, svga->curr.tes);626util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,627(struct pipe_stream_output_target**)svga->so_targets);628util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);629util_blitter_save_viewport(svga->blitter, &svga->curr.viewport[0]);630util_blitter_save_scissor(svga->blitter, &svga->curr.scissor[0]);631util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);632util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);633util_blitter_save_depth_stencil_alpha(svga->blitter,634(void*)svga->curr.depth);635util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref);636util_blitter_save_sample_mask(svga->blitter, svga->curr.sample_mask);637util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer);638util_blitter_save_fragment_sampler_states(svga->blitter,639svga->curr.num_samplers[PIPE_SHADER_FRAGMENT],640(void**)svga->curr.sampler[PIPE_SHADER_FRAGMENT]);641util_blitter_save_fragment_sampler_views(svga->blitter,642svga->curr.num_sampler_views[PIPE_SHADER_FRAGMENT],643svga->curr.sampler_views[PIPE_SHADER_FRAGMENT]);644645if (!can_create_src_view) {646struct pipe_resource template;647struct pipe_blit_info copy_region_blit;648649/**650* If the source blit format is not compatible with the source resource651* format, we will not be able to create a shader resource view.652* In order to avoid falling back to software blit, we'll create653* a new resource in the blit format, and use DXCopyResource to654* copy from the original format to the new format. The new655* resource will be used for the blit in util_blitter_blit().656*/657template = *src;658template.format = blit.src.format;659newSrc = svga_texture_create(svga->pipe.screen, &template);660if (newSrc == NULL) {661debug_printf("svga_blit: fails to create temporary src\n");662ret = false;663goto done;664}665666/* increment the mksStats for blitter with extra copy */667SVGA_STATS_COUNT_INC(sws, SVGA_STATS_COUNT_BLITBLITTERCOPY);668build_blit_info(newSrc,669blit.src.level, blit.src.box.x,670blit.src.box.y, blit.src.box.z,671blit.src.resource,672blit.src.level, &blit.src.box,673©_region_blit);674if (!try_copy_region(svga, ©_region_blit)) {675debug_printf("svga: Source blit format conversion failed.\n");676ret = false;677goto done;678}679680blit.src.resource = newSrc;681}682683if (!can_create_dst_view) {684struct pipe_resource template;685686/*687* If the destination blit format is not compatible with the destination688* resource format, we will not be able to create a render target view.689* In order to avoid falling back to software blit, we'll create690* a new resource in the blit format, and use DXPredCopyRegion691* after the blit to copy from the blit format back to the resource692* format.693*/694template = *dst;695template.format = blit.dst.format;696newDst = svga_texture_create(svga->pipe.screen, &template);697if (newDst == NULL) {698debug_printf("svga_blit: fails to create temporary dst\n");699ret = false;700goto done;701}702703blit.dst.resource = newDst;704}705706svga_toggle_render_condition(svga, blit.render_condition_enable, FALSE);707708util_blitter_blit(svga->blitter, &blit);709710svga_toggle_render_condition(svga, blit.render_condition_enable, TRUE);711712if (blit.dst.resource != dst) {713struct pipe_blit_info copy_region_blit;714715/* increment the mksStats for blitter with extra copy */716SVGA_STATS_COUNT_INC(sws, SVGA_STATS_COUNT_BLITBLITTERCOPY);717718/*719* A temporary resource was created for the blit, we need to720* copy from the temporary resource back to the original destination.721*/722build_blit_info(dst,723blit.dst.level, blit.dst.box.x,724blit.dst.box.y, blit.dst.box.z,725newDst,726blit.dst.level, &blit.dst.box,727©_region_blit);728if (!try_copy_region(svga, ©_region_blit)) {729debug_printf("svga: Destination blit format conversion failed.\n");730ret = false;731goto done;732}733}734735done:736/* unreference the temporary resources if needed */737pipe_resource_reference(&newDst, NULL);738pipe_resource_reference(&newSrc, NULL);739740SVGA_STATS_TIME_POP(sws); /* SVGA_STATS_TIME_BLITBLITTER */741(void) sws;742743return ret;744}745746747/**748* Try a cpu copy_region fallback.749*/750static bool751try_cpu_copy_region(struct svga_context *svga,752const struct pipe_blit_info *blit)753{754if (util_can_blit_via_copy_region(blit, TRUE) ||755util_can_blit_via_copy_region(blit, FALSE)) {756757if (svga->render_condition && blit->render_condition_enable) {758debug_warning("CPU copy_region doesn't support "759"conditional rendering.\n");760return false;761}762763copy_region_fallback(svga, blit->dst.resource,764blit->dst.level,765blit->dst.box.x, blit->dst.box.y,766blit->dst.box.z, blit->src.resource,767blit->src.level, &blit->src.box);768return true;769}770771return false;772}773774775/**776* The pipe::blit member.777*/778static void779svga_blit(struct pipe_context *pipe,780const struct pipe_blit_info *blit)781{782struct svga_context *svga = svga_context(pipe);783struct svga_winsys_screen *sws = svga_screen(pipe->screen)->sws;784785if (!svga_have_vgpu10(svga) &&786blit->src.resource->nr_samples > 1 &&787blit->dst.resource->nr_samples <= 1 &&788!util_format_is_depth_or_stencil(blit->src.resource->format) &&789!util_format_is_pure_integer(blit->src.resource->format)) {790debug_printf("svga: color resolve unimplemented\n");791return;792}793794SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_BLIT);795796if (try_copy_region(svga, blit))797goto done;798799if (try_blit(svga, blit))800goto done;801802if (!try_cpu_copy_region(svga, blit))803debug_printf("svga: Blit failed.\n");804805done:806SVGA_STATS_TIME_POP(sws); /* SVGA_STATS_TIME_BLIT */807(void) sws;808}809810811/**812* The pipe::resource_copy_region member.813*/814static void815svga_resource_copy_region(struct pipe_context *pipe,816struct pipe_resource *dst_tex,817unsigned dst_level,818unsigned dstx, unsigned dsty, unsigned dstz,819struct pipe_resource *src_tex,820unsigned src_level,821const struct pipe_box *src_box)822{823struct svga_context *svga = svga_context(pipe);824struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;825826SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_COPYREGION);827828if (dst_tex->target == PIPE_BUFFER && src_tex->target == PIPE_BUFFER) {829/* can't copy within the same buffer, unfortunately */830if (svga_have_vgpu10(svga) && src_tex != dst_tex) {831struct svga_winsys_surface *src_surf;832struct svga_winsys_surface *dst_surf;833struct svga_buffer *dbuffer = svga_buffer(dst_tex);834struct svga_buffer *sbuffer = svga_buffer(src_tex);835836src_surf = svga_buffer_handle(svga, src_tex, sbuffer->bind_flags);837dst_surf = svga_buffer_handle(svga, dst_tex, dbuffer->bind_flags);838839SVGA_RETRY(svga, SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf,840dst_surf, src_box->x, dstx,841src_box->width));842dbuffer->dirty = TRUE;843}844else {845/* use map/memcpy fallback */846copy_region_fallback(svga, dst_tex, dst_level, dstx,847dsty, dstz, src_tex, src_level, src_box);848}849} else {850struct pipe_blit_info blit;851852build_blit_info(dst_tex, dst_level, dstx, dsty, dstz,853src_tex, src_level, src_box, &blit);854855if (try_copy_region(svga, &blit))856goto done;857858/* Blits are format-converting which is not what we want, so perform a859* strict format-check.860* FIXME: Need to figure out why srgb blits (tf2) and861* 3D blits (piglit) are broken here. Perhaps we set up the862* struct pipe_blit_info incorrectly.863*/864if (src_tex->format == dst_tex->format &&865!util_format_is_srgb(src_tex->format) &&866svga_resource_type(src_tex->target) != SVGA3D_RESOURCE_TEXTURE3D &&867try_blit(svga, &blit))868goto done;869870copy_region_fallback(svga, dst_tex, dst_level, dstx, dsty, dstz,871src_tex, src_level, src_box);872}873874done:875SVGA_STATS_TIME_POP(sws);876(void) sws;877}878879880/**881* The pipe::flush_resource member.882*/883static void884svga_flush_resource(struct pipe_context *pipe,885struct pipe_resource *resource)886{887}888889890/**891* Setup the pipe blit, resource_copy_region and flush_resource members.892*/893void894svga_init_blit_functions(struct svga_context *svga)895{896svga->pipe.resource_copy_region = svga_resource_copy_region;897svga->pipe.blit = svga_blit;898svga->pipe.flush_resource = svga_flush_resource;899}900901902