Path: blob/21.2-virgl/src/gallium/drivers/i915/i915_surface.c
4570 views
/**************************************************************************1*2* Copyright 2003 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include "i915_surface.h"28#include "pipe/p_defines.h"29#include "util/format/u_format.h"30#include "util/u_inlines.h"31#include "util/u_math.h"32#include "util/u_memory.h"33#include "util/u_pack_color.h"34#include "util/u_surface.h"35#include "i915_blit.h"36#include "i915_reg.h"37#include "i915_resource.h"38#include "i915_screen.h"39#include "i915_state.h"4041static struct pipe_surface *42i915_create_surface_custom(struct pipe_context *ctx, struct pipe_resource *pt,43const struct pipe_surface *surf_tmpl,44unsigned width0, unsigned height0);45/*46* surface functions using the render engine47*/4849static void50i915_util_blitter_save_states(struct i915_context *i915)51{52util_blitter_save_blend(i915->blitter, (void *)i915->blend);53util_blitter_save_depth_stencil_alpha(i915->blitter,54(void *)i915->depth_stencil);55util_blitter_save_stencil_ref(i915->blitter, &i915->stencil_ref);56util_blitter_save_rasterizer(i915->blitter, (void *)i915->rasterizer);57util_blitter_save_fragment_shader(i915->blitter, i915->fs);58util_blitter_save_vertex_shader(i915->blitter, i915->vs);59util_blitter_save_viewport(i915->blitter, &i915->viewport);60util_blitter_save_scissor(i915->blitter, &i915->scissor);61util_blitter_save_vertex_elements(i915->blitter, i915->velems);62util_blitter_save_vertex_buffer_slot(i915->blitter, i915->vertex_buffers);6364util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);6566util_blitter_save_fragment_sampler_states(i915->blitter, i915->num_samplers,67(void **)i915->fragment_sampler);68util_blitter_save_fragment_sampler_views(i915->blitter,69i915->num_fragment_sampler_views,70i915->fragment_sampler_views);71}7273static void74i915_surface_copy_render(struct pipe_context *pipe, struct pipe_resource *dst,75unsigned dst_level, unsigned dstx, unsigned dsty,76unsigned dstz, struct pipe_resource *src,77unsigned src_level, const struct pipe_box *src_box)78{79struct i915_context *i915 = i915_context(pipe);80unsigned src_width0 = src->width0;81unsigned src_height0 = src->height0;82unsigned dst_width0 = dst->width0;83unsigned dst_height0 = dst->height0;84struct pipe_box dstbox;85struct pipe_sampler_view src_templ, *src_view;86struct pipe_surface dst_templ, *dst_view;87const struct util_format_description *desc;8889/* Fallback for buffers. */90if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER)91goto fallback;9293/* Fallback for depth&stencil. XXX: see if we can use a proxy format */94desc = util_format_description(src->format);95if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)96goto fallback;9798desc = util_format_description(dst->format);99if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)100goto fallback;101102util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);103util_blitter_default_src_texture(i915->blitter, &src_templ, src, src_level);104105if (!util_blitter_is_copy_supported(i915->blitter, dst, src))106goto fallback;107108i915_util_blitter_save_states(i915);109110dst_view = i915_create_surface_custom(pipe, dst, &dst_templ, dst_width0,111dst_height0);112src_view = i915_create_sampler_view_custom(pipe, src, &src_templ, src_width0,113src_height0);114115u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height),116abs(src_box->depth), &dstbox);117118util_blitter_blit_generic(i915->blitter, dst_view, &dstbox, src_view,119src_box, src_width0, src_height0, PIPE_MASK_RGBAZS,120PIPE_TEX_FILTER_NEAREST, NULL, false);121return;122123fallback:124util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src,125src_level, src_box);126}127128static void129i915_clear_render_target_render(struct pipe_context *pipe,130struct pipe_surface *dst,131const union pipe_color_union *color,132unsigned dstx, unsigned dsty, unsigned width,133unsigned height, bool render_condition_enabled)134{135struct i915_context *i915 = i915_context(pipe);136struct pipe_framebuffer_state fb_state;137138util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);139140fb_state.width = dst->width;141fb_state.height = dst->height;142fb_state.nr_cbufs = 1;143fb_state.cbufs[0] = dst;144fb_state.zsbuf = NULL;145pipe->set_framebuffer_state(pipe, &fb_state);146147if (i915->dirty)148i915_update_derived(i915);149150i915_clear_emit(pipe, PIPE_CLEAR_COLOR, color, 0.0, 0x0, dstx, dsty, width,151height);152153pipe->set_framebuffer_state(pipe, &i915->blitter->saved_fb_state);154util_unreference_framebuffer_state(&i915->blitter->saved_fb_state);155i915->blitter->saved_fb_state.nr_cbufs = ~0;156}157158static void159i915_clear_depth_stencil_render(struct pipe_context *pipe,160struct pipe_surface *dst, unsigned clear_flags,161double depth, unsigned stencil, unsigned dstx,162unsigned dsty, unsigned width, unsigned height,163bool render_condition_enabled)164{165struct i915_context *i915 = i915_context(pipe);166struct pipe_framebuffer_state fb_state;167168util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);169170fb_state.width = dst->width;171fb_state.height = dst->height;172fb_state.nr_cbufs = 0;173fb_state.zsbuf = dst;174pipe->set_framebuffer_state(pipe, &fb_state);175176if (i915->dirty)177i915_update_derived(i915);178179i915_clear_emit(pipe, clear_flags & PIPE_CLEAR_DEPTHSTENCIL, NULL, depth,180stencil, dstx, dsty, width, height);181182pipe->set_framebuffer_state(pipe, &i915->blitter->saved_fb_state);183util_unreference_framebuffer_state(&i915->blitter->saved_fb_state);184i915->blitter->saved_fb_state.nr_cbufs = ~0;185}186187/*188* surface functions using the blitter189*/190191/* Assumes all values are within bounds -- no checking at this level -192* do it higher up if required.193*/194static void195i915_surface_copy_blitter(struct pipe_context *pipe, struct pipe_resource *dst,196unsigned dst_level, unsigned dstx, unsigned dsty,197unsigned dstz, struct pipe_resource *src,198unsigned src_level, const struct pipe_box *src_box)199{200/* Fallback for buffers. */201if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {202util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src,203src_level, src_box);204return;205}206207struct i915_texture *dst_tex = i915_texture(dst);208struct i915_texture *src_tex = i915_texture(src);209struct pipe_resource *dpt = &dst_tex->b;210ASSERTED struct pipe_resource *spt = &src_tex->b;211unsigned dst_offset, src_offset; /* in bytes */212213/* XXX cannot copy 3d regions at this time */214assert(src_box->depth == 1);215if (dst->target != PIPE_TEXTURE_CUBE && dst->target != PIPE_TEXTURE_3D)216assert(dstz == 0);217dst_offset = i915_texture_offset(dst_tex, dst_level, dstz);218219if (src->target != PIPE_TEXTURE_CUBE && src->target != PIPE_TEXTURE_3D)220assert(src_box->z == 0);221src_offset = i915_texture_offset(src_tex, src_level, src_box->z);222223assert(util_format_get_blocksize(dpt->format) ==224util_format_get_blocksize(spt->format));225assert(util_format_get_blockwidth(dpt->format) ==226util_format_get_blockwidth(spt->format));227assert(util_format_get_blockheight(dpt->format) ==228util_format_get_blockheight(spt->format));229assert(util_format_get_blockwidth(dpt->format) == 1);230assert(util_format_get_blockheight(dpt->format) == 1);231232i915_copy_blit(i915_context(pipe), util_format_get_blocksize(dpt->format),233(unsigned short)src_tex->stride, src_tex->buffer, src_offset,234(unsigned short)dst_tex->stride, dst_tex->buffer, dst_offset,235(short)src_box->x, (short)src_box->y, (short)dstx,236(short)dsty, (short)src_box->width, (short)src_box->height);237}238239static void240i915_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info)241{242struct i915_context *i915 = i915_context(pipe);243struct pipe_blit_info info = *blit_info;244245if (util_try_blit_via_copy_region(pipe, &info)) {246return; /* done */247}248249if (info.mask & PIPE_MASK_S) {250debug_printf("i915: cannot blit stencil, skipping\n");251info.mask &= ~PIPE_MASK_S;252}253254if (!util_blitter_is_blit_supported(i915->blitter, &info)) {255debug_printf("i915: blit unsupported %s -> %s\n",256util_format_short_name(info.src.resource->format),257util_format_short_name(info.dst.resource->format));258return;259}260261i915_util_blitter_save_states(i915);262263util_blitter_blit(i915->blitter, &info);264}265266static void267i915_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)268{269}270271static void272i915_clear_render_target_blitter(struct pipe_context *pipe,273struct pipe_surface *dst,274const union pipe_color_union *color,275unsigned dstx, unsigned dsty, unsigned width,276unsigned height, bool render_condition_enabled)277{278struct i915_texture *tex = i915_texture(dst->texture);279struct pipe_resource *pt = &tex->b;280union util_color uc;281unsigned offset =282i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);283284assert(util_format_get_blockwidth(pt->format) == 1);285assert(util_format_get_blockheight(pt->format) == 1);286287util_pack_color(color->f, dst->format, &uc);288i915_fill_blit(i915_context(pipe), util_format_get_blocksize(pt->format),289XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB,290(unsigned short)tex->stride, tex->buffer, offset, (short)dstx,291(short)dsty, (short)width, (short)height, uc.ui[0]);292}293294static void295i915_clear_depth_stencil_blitter(struct pipe_context *pipe,296struct pipe_surface *dst, unsigned clear_flags,297double depth, unsigned stencil, unsigned dstx,298unsigned dsty, unsigned width, unsigned height,299bool render_condition_enabled)300{301struct i915_texture *tex = i915_texture(dst->texture);302struct pipe_resource *pt = &tex->b;303unsigned packedds;304unsigned mask = 0;305unsigned offset =306i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);307308assert(util_format_get_blockwidth(pt->format) == 1);309assert(util_format_get_blockheight(pt->format) == 1);310311packedds = util_pack_z_stencil(dst->format, depth, stencil);312313if (clear_flags & PIPE_CLEAR_DEPTH)314mask |= XY_COLOR_BLT_WRITE_RGB;315/* XXX presumably this does read-modify-write316(otherwise this won't work anyway). Hence will only want to317do it if really have stencil and it isn't cleared */318if ((clear_flags & PIPE_CLEAR_STENCIL) ||319(dst->format != PIPE_FORMAT_Z24_UNORM_S8_UINT))320mask |= XY_COLOR_BLT_WRITE_ALPHA;321322i915_fill_blit(i915_context(pipe), util_format_get_blocksize(pt->format),323mask, (unsigned short)tex->stride, tex->buffer, offset,324(short)dstx, (short)dsty, (short)width, (short)height,325packedds);326}327328/*329* Screen surface functions330*/331332static void333i915_set_color_surface_swizzle(struct i915_surface *surf)334{335enum pipe_format format = surf->templ.format;336337const struct {338enum pipe_format format;339uint8_t color_swizzle[4];340uint32_t oc_swizzle;341} fixup_formats[] = {342{PIPE_FORMAT_R8G8B8A8_UNORM, {2, 1, 0, 3}, 0x21030000 /* BGRA */},343{PIPE_FORMAT_R8G8B8X8_UNORM, {2, 1, 0, 3}, 0x21030000 /* BGRX */},344345/* These are rendered to using COLORBUF_8BIT, where the G channel written346* by shader (and output by blending) is used.347*/348{PIPE_FORMAT_L8_UNORM, {0, 0, 0, 0}, 0x00030000 /* RRRA */},349{PIPE_FORMAT_I8_UNORM, {0, 0, 0, 0}, 0x00030000 /* RRRA */},350{PIPE_FORMAT_A8_UNORM, {3, 3, 3, 3}, 0x33330000 /* AAAA */},351};352353if (format == PIPE_FORMAT_A8_UNORM)354surf->alpha_in_g = true;355else if (util_format_is_rgbx_or_bgrx(format))356surf->alpha_is_x = true;357358for (int i = 0; i < ARRAY_SIZE(fixup_formats); i++) {359if (fixup_formats[i].format == format) {360memcpy(surf->color_swizzle, fixup_formats[i].color_swizzle,361sizeof(surf->color_swizzle));362surf->oc_swizzle = fixup_formats[i].oc_swizzle;363return;364}365}366367for (int i = 0; i < 4; i++)368surf->color_swizzle[i] = i;369}370371static struct pipe_surface *372i915_create_surface_custom(struct pipe_context *ctx, struct pipe_resource *pt,373const struct pipe_surface *surf_tmpl,374unsigned width0, unsigned height0)375{376struct i915_texture *tex = i915_texture(pt);377struct i915_surface *surf;378379assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);380if (pt->target != PIPE_TEXTURE_CUBE && pt->target != PIPE_TEXTURE_3D)381assert(surf_tmpl->u.tex.first_layer == 0);382383surf = CALLOC_STRUCT(i915_surface);384if (!surf)385return NULL;386387struct pipe_surface *ps = &surf->templ;388389pipe_reference_init(&ps->reference, 1);390pipe_resource_reference(&ps->texture, pt);391ps->format = surf_tmpl->format;392ps->width = u_minify(width0, surf_tmpl->u.tex.level);393ps->height = u_minify(height0, surf_tmpl->u.tex.level);394ps->u.tex.level = surf_tmpl->u.tex.level;395ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;396ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;397ps->context = ctx;398399if (util_format_is_depth_or_stencil(ps->format)) {400surf->buf_info = BUF_3D_ID_DEPTH;401} else {402surf->buf_info = BUF_3D_ID_COLOR_BACK;403404i915_set_color_surface_swizzle(surf);405}406407surf->buf_info |= BUF_3D_PITCH(tex->stride); /* pitch in bytes */408409switch (tex->tiling) {410case I915_TILE_Y:411surf->buf_info |= BUF_3D_TILED_SURFACE | BUF_3D_TILE_WALK_Y;412break;413case I915_TILE_X:414surf->buf_info |= BUF_3D_TILED_SURFACE;415break;416case I915_TILE_NONE:417break;418}419420return ps;421}422423static struct pipe_surface *424i915_create_surface(struct pipe_context *ctx, struct pipe_resource *pt,425const struct pipe_surface *surf_tmpl)426{427return i915_create_surface_custom(ctx, pt, surf_tmpl, pt->width0,428pt->height0);429}430431static void432i915_surface_destroy(struct pipe_context *ctx, struct pipe_surface *surf)433{434pipe_resource_reference(&surf->texture, NULL);435FREE(surf);436}437438void439i915_init_surface_functions(struct i915_context *i915)440{441if (i915_screen(i915->base.screen)->debug.use_blitter) {442i915->base.resource_copy_region = i915_surface_copy_blitter;443i915->base.clear_render_target = i915_clear_render_target_blitter;444i915->base.clear_depth_stencil = i915_clear_depth_stencil_blitter;445} else {446i915->base.resource_copy_region = i915_surface_copy_render;447i915->base.clear_render_target = i915_clear_render_target_render;448i915->base.clear_depth_stencil = i915_clear_depth_stencil_render;449}450i915->base.blit = i915_blit;451i915->base.flush_resource = i915_flush_resource;452i915->base.create_surface = i915_create_surface;453i915->base.surface_destroy = i915_surface_destroy;454}455456457