Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv50/nv50_surface.c
4574 views
/*1* Copyright 2008 Ben Skeggs2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*/2122#include <stdint.h>2324#include "pipe/p_defines.h"2526#include "util/u_inlines.h"27#include "util/u_pack_color.h"28#include "util/format/u_format.h"29#include "util/u_math.h"30#include "util/u_surface.h"3132#include "tgsi/tgsi_ureg.h"3334#include "os/os_thread.h"3536#include "nv50/nv50_context.h"37#include "nv50/nv50_resource.h"3839#include "nv50/g80_defs.xml.h"40#include "nv50/g80_texture.xml.h"4142/* these are used in nv50_blit.h */43#define NV50_ENG2D_SUPPORTED_FORMATS 0xff0843e080608409ULL44#define NV50_ENG2D_NOCONVERT_FORMATS 0x0008402000000000ULL45#define NV50_ENG2D_LUMINANCE_FORMATS 0x0008402000000000ULL46#define NV50_ENG2D_INTENSITY_FORMATS 0x0000000000000000ULL47#define NV50_ENG2D_OPERATION_FORMATS 0x060001c000608000ULL4849#define NOUVEAU_DRIVER 0x5050#include "nv50/nv50_blit.h"5152static inline uint8_t53nv50_2d_format(enum pipe_format format, bool dst, bool dst_src_equal)54{55uint8_t id = nv50_format_table[format].rt;5657/* Hardware values for color formats range from 0xc0 to 0xff,58* but the 2D engine doesn't support all of them.59*/60if ((id >= 0xc0) && (NV50_ENG2D_SUPPORTED_FORMATS & (1ULL << (id - 0xc0))))61return id;62assert(dst_src_equal);6364switch (util_format_get_blocksize(format)) {65case 1:66return G80_SURFACE_FORMAT_R8_UNORM;67case 2:68return G80_SURFACE_FORMAT_R16_UNORM;69case 4:70return G80_SURFACE_FORMAT_BGRA8_UNORM;71case 8:72return G80_SURFACE_FORMAT_RGBA16_FLOAT;73case 16:74return G80_SURFACE_FORMAT_RGBA32_FLOAT;75default:76return 0;77}78}7980static int81nv50_2d_texture_set(struct nouveau_pushbuf *push, int dst,82struct nv50_miptree *mt, unsigned level, unsigned layer,83enum pipe_format pformat, bool dst_src_pformat_equal)84{85struct nouveau_bo *bo = mt->base.bo;86uint32_t width, height, depth;87uint32_t format;88uint32_t mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;89uint32_t offset = mt->level[level].offset;9091format = nv50_2d_format(pformat, dst, dst_src_pformat_equal);92if (!format) {93NOUVEAU_ERR("invalid/unsupported surface format: %s\n",94util_format_name(pformat));95return 1;96}9798width = u_minify(mt->base.base.width0, level) << mt->ms_x;99height = u_minify(mt->base.base.height0, level) << mt->ms_y;100depth = u_minify(mt->base.base.depth0, level);101102offset = mt->level[level].offset;103if (!mt->layout_3d) {104offset += mt->layer_stride * layer;105depth = 1;106layer = 0;107} else108if (!dst) {109offset += nv50_mt_zslice_offset(mt, level, layer);110layer = 0;111}112113if (!nouveau_bo_memtype(bo)) {114BEGIN_NV04(push, SUBC_2D(mthd), 2);115PUSH_DATA (push, format);116PUSH_DATA (push, 1);117BEGIN_NV04(push, SUBC_2D(mthd + 0x14), 5);118PUSH_DATA (push, mt->level[level].pitch);119PUSH_DATA (push, width);120PUSH_DATA (push, height);121PUSH_DATAh(push, mt->base.address + offset);122PUSH_DATA (push, mt->base.address + offset);123} else {124BEGIN_NV04(push, SUBC_2D(mthd), 5);125PUSH_DATA (push, format);126PUSH_DATA (push, 0);127PUSH_DATA (push, mt->level[level].tile_mode);128PUSH_DATA (push, depth);129PUSH_DATA (push, layer);130BEGIN_NV04(push, SUBC_2D(mthd + 0x18), 4);131PUSH_DATA (push, width);132PUSH_DATA (push, height);133PUSH_DATAh(push, mt->base.address + offset);134PUSH_DATA (push, mt->base.address + offset);135}136137#if 0138if (dst) {139BEGIN_NV04(push, SUBC_2D(NV50_2D_CLIP_X), 4);140PUSH_DATA (push, 0);141PUSH_DATA (push, 0);142PUSH_DATA (push, width);143PUSH_DATA (push, height);144}145#endif146return 0;147}148149static int150nv50_2d_texture_do_copy(struct nouveau_pushbuf *push,151struct nv50_miptree *dst, unsigned dst_level,152unsigned dx, unsigned dy, unsigned dz,153struct nv50_miptree *src, unsigned src_level,154unsigned sx, unsigned sy, unsigned sz,155unsigned w, unsigned h)156{157const enum pipe_format dfmt = dst->base.base.format;158const enum pipe_format sfmt = src->base.base.format;159int ret;160bool eqfmt = dfmt == sfmt;161162if (!PUSH_SPACE(push, 2 * 16 + 32))163return PIPE_ERROR;164165ret = nv50_2d_texture_set(push, 1, dst, dst_level, dz, dfmt, eqfmt);166if (ret)167return ret;168169ret = nv50_2d_texture_set(push, 0, src, src_level, sz, sfmt, eqfmt);170if (ret)171return ret;172173BEGIN_NV04(push, NV50_2D(BLIT_CONTROL), 1);174PUSH_DATA (push, NV50_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE);175BEGIN_NV04(push, NV50_2D(BLIT_DST_X), 4);176PUSH_DATA (push, dx << dst->ms_x);177PUSH_DATA (push, dy << dst->ms_y);178PUSH_DATA (push, w << dst->ms_x);179PUSH_DATA (push, h << dst->ms_y);180BEGIN_NV04(push, NV50_2D(BLIT_DU_DX_FRACT), 4);181PUSH_DATA (push, 0);182PUSH_DATA (push, 1);183PUSH_DATA (push, 0);184PUSH_DATA (push, 1);185BEGIN_NV04(push, NV50_2D(BLIT_SRC_X_FRACT), 4);186PUSH_DATA (push, 0);187PUSH_DATA (push, sx << src->ms_x);188PUSH_DATA (push, 0);189PUSH_DATA (push, sy << src->ms_y);190191return 0;192}193194static void195nv50_resource_copy_region(struct pipe_context *pipe,196struct pipe_resource *dst, unsigned dst_level,197unsigned dstx, unsigned dsty, unsigned dstz,198struct pipe_resource *src, unsigned src_level,199const struct pipe_box *src_box)200{201struct nv50_context *nv50 = nv50_context(pipe);202int ret;203bool m2mf;204unsigned dst_layer = dstz, src_layer = src_box->z;205206if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {207nouveau_copy_buffer(&nv50->base,208nv04_resource(dst), dstx,209nv04_resource(src), src_box->x, src_box->width);210return;211}212213/* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */214assert((src->nr_samples | 1) == (dst->nr_samples | 1));215216m2mf = (src->format == dst->format) ||217(util_format_get_blocksizebits(src->format) ==218util_format_get_blocksizebits(dst->format));219220nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;221222if (m2mf) {223struct nv50_miptree *src_mt = nv50_miptree(src);224struct nv50_miptree *dst_mt = nv50_miptree(dst);225struct nv50_m2mf_rect drect, srect;226unsigned i;227unsigned nx = util_format_get_nblocksx(src->format, src_box->width)228<< src_mt->ms_x;229unsigned ny = util_format_get_nblocksy(src->format, src_box->height)230<< src_mt->ms_y;231232nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);233nv50_m2mf_rect_setup(&srect, src, src_level,234src_box->x, src_box->y, src_box->z);235236for (i = 0; i < src_box->depth; ++i) {237nv50_m2mf_transfer_rect(nv50, &drect, &srect, nx, ny);238239if (dst_mt->layout_3d)240drect.z++;241else242drect.base += dst_mt->layer_stride;243244if (src_mt->layout_3d)245srect.z++;246else247srect.base += src_mt->layer_stride;248}249return;250}251252assert((src->format == dst->format) ||253(nv50_2d_src_format_faithful(src->format) &&254nv50_2d_dst_format_faithful(dst->format)));255256BCTX_REFN(nv50->bufctx, 2D, nv04_resource(src), RD);257BCTX_REFN(nv50->bufctx, 2D, nv04_resource(dst), WR);258nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx);259nouveau_pushbuf_validate(nv50->base.pushbuf);260261for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {262ret = nv50_2d_texture_do_copy(nv50->base.pushbuf,263nv50_miptree(dst), dst_level,264dstx, dsty, dst_layer,265nv50_miptree(src), src_level,266src_box->x, src_box->y, src_layer,267src_box->width, src_box->height);268if (ret)269break;270}271nouveau_bufctx_reset(nv50->bufctx, NV50_BIND_2D);272}273274static void275nv50_clear_render_target(struct pipe_context *pipe,276struct pipe_surface *dst,277const union pipe_color_union *color,278unsigned dstx, unsigned dsty,279unsigned width, unsigned height,280bool render_condition_enabled)281{282struct nv50_context *nv50 = nv50_context(pipe);283struct nouveau_pushbuf *push = nv50->base.pushbuf;284struct nv50_miptree *mt = nv50_miptree(dst->texture);285struct nv50_surface *sf = nv50_surface(dst);286struct nouveau_bo *bo = mt->base.bo;287unsigned z;288289assert(dst->texture->target != PIPE_BUFFER);290291BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4);292PUSH_DATAf(push, color->f[0]);293PUSH_DATAf(push, color->f[1]);294PUSH_DATAf(push, color->f[2]);295PUSH_DATAf(push, color->f[3]);296297if (nouveau_pushbuf_space(push, 64 + sf->depth, 1, 0))298return;299300PUSH_REFN(push, bo, mt->base.domain | NOUVEAU_BO_WR);301302BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);303PUSH_DATA (push, ( width << 16) | dstx);304PUSH_DATA (push, (height << 16) | dsty);305BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);306PUSH_DATA (push, 8192 << 16);307PUSH_DATA (push, 8192 << 16);308nv50->scissors_dirty |= 1;309310BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);311PUSH_DATA (push, 1);312BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5);313PUSH_DATAh(push, mt->base.address + sf->offset);314PUSH_DATA (push, mt->base.address + sf->offset);315PUSH_DATA (push, nv50_format_table[dst->format].rt);316PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);317PUSH_DATA (push, mt->layer_stride >> 2);318BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);319if (nouveau_bo_memtype(bo))320PUSH_DATA(push, sf->width);321else322PUSH_DATA(push, NV50_3D_RT_HORIZ_LINEAR | mt->level[0].pitch);323PUSH_DATA (push, sf->height);324BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);325if (mt->layout_3d)326PUSH_DATA(push, NV50_3D_RT_ARRAY_MODE_MODE_3D | 512);327else328PUSH_DATA(push, 512);329330BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);331PUSH_DATA (push, mt->ms_mode);332333if (!nouveau_bo_memtype(bo)) {334BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);335PUSH_DATA (push, 0);336}337338/* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */339340BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);341PUSH_DATA (push, (width << 16) | dstx);342PUSH_DATA (push, (height << 16) | dsty);343344if (!render_condition_enabled) {345BEGIN_NV04(push, NV50_3D(COND_MODE), 1);346PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);347}348349BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), sf->depth);350for (z = 0; z < sf->depth; ++z) {351PUSH_DATA (push, 0x3c |352(z << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));353}354355if (!render_condition_enabled) {356BEGIN_NV04(push, NV50_3D(COND_MODE), 1);357PUSH_DATA (push, nv50->cond_condmode);358}359360nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_SCISSOR;361}362363static void364nv50_clear_depth_stencil(struct pipe_context *pipe,365struct pipe_surface *dst,366unsigned clear_flags,367double depth,368unsigned stencil,369unsigned dstx, unsigned dsty,370unsigned width, unsigned height,371bool render_condition_enabled)372{373struct nv50_context *nv50 = nv50_context(pipe);374struct nouveau_pushbuf *push = nv50->base.pushbuf;375struct nv50_miptree *mt = nv50_miptree(dst->texture);376struct nv50_surface *sf = nv50_surface(dst);377struct nouveau_bo *bo = mt->base.bo;378uint32_t mode = 0;379unsigned z;380381assert(dst->texture->target != PIPE_BUFFER);382assert(nouveau_bo_memtype(bo)); /* ZETA cannot be linear */383384if (clear_flags & PIPE_CLEAR_DEPTH) {385BEGIN_NV04(push, NV50_3D(CLEAR_DEPTH), 1);386PUSH_DATAf(push, depth);387mode |= NV50_3D_CLEAR_BUFFERS_Z;388}389390if (clear_flags & PIPE_CLEAR_STENCIL) {391BEGIN_NV04(push, NV50_3D(CLEAR_STENCIL), 1);392PUSH_DATA (push, stencil & 0xff);393mode |= NV50_3D_CLEAR_BUFFERS_S;394}395396if (nouveau_pushbuf_space(push, 64 + sf->depth, 1, 0))397return;398399PUSH_REFN(push, bo, mt->base.domain | NOUVEAU_BO_WR);400401BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);402PUSH_DATA (push, ( width << 16) | dstx);403PUSH_DATA (push, (height << 16) | dsty);404BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);405PUSH_DATA (push, 8192 << 16);406PUSH_DATA (push, 8192 << 16);407nv50->scissors_dirty |= 1;408409BEGIN_NV04(push, NV50_3D(ZETA_ADDRESS_HIGH), 5);410PUSH_DATAh(push, mt->base.address + sf->offset);411PUSH_DATA (push, mt->base.address + sf->offset);412PUSH_DATA (push, nv50_format_table[dst->format].rt);413PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);414PUSH_DATA (push, mt->layer_stride >> 2);415BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);416PUSH_DATA (push, 1);417BEGIN_NV04(push, NV50_3D(ZETA_HORIZ), 3);418PUSH_DATA (push, sf->width);419PUSH_DATA (push, sf->height);420PUSH_DATA (push, (1 << 16) | 1);421422BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);423PUSH_DATA (push, 512);424425BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);426PUSH_DATA (push, mt->ms_mode);427428BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);429PUSH_DATA (push, (width << 16) | dstx);430PUSH_DATA (push, (height << 16) | dsty);431432if (!render_condition_enabled) {433BEGIN_NV04(push, NV50_3D(COND_MODE), 1);434PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);435}436437BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), sf->depth);438for (z = 0; z < sf->depth; ++z) {439PUSH_DATA (push, mode |440(z << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));441}442443if (!render_condition_enabled) {444BEGIN_NV04(push, NV50_3D(COND_MODE), 1);445PUSH_DATA (push, nv50->cond_condmode);446}447448nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_SCISSOR;449}450451void452nv50_clear_texture(struct pipe_context *pipe,453struct pipe_resource *res,454unsigned level,455const struct pipe_box *box,456const void *data)457{458struct pipe_surface tmpl = {{0}}, *sf;459460tmpl.format = res->format;461tmpl.u.tex.first_layer = box->z;462tmpl.u.tex.last_layer = box->z + box->depth - 1;463tmpl.u.tex.level = level;464sf = pipe->create_surface(pipe, res, &tmpl);465if (!sf)466return;467468if (util_format_is_depth_or_stencil(res->format)) {469float depth = 0;470uint8_t stencil = 0;471unsigned clear = 0;472const struct util_format_description *desc =473util_format_description(res->format);474475if (util_format_has_depth(desc)) {476clear |= PIPE_CLEAR_DEPTH;477util_format_unpack_z_float(res->format, &depth, data, 1);478}479if (util_format_has_stencil(desc)) {480clear |= PIPE_CLEAR_STENCIL;481util_format_unpack_s_8uint(res->format, &stencil, data, 1);482}483pipe->clear_depth_stencil(pipe, sf, clear, depth, stencil,484box->x, box->y, box->width, box->height, false);485} else {486union pipe_color_union color;487488switch (util_format_get_blocksizebits(res->format)) {489case 128:490sf->format = PIPE_FORMAT_R32G32B32A32_UINT;491memcpy(&color.ui, data, 128 / 8);492break;493case 64:494sf->format = PIPE_FORMAT_R32G32_UINT;495memcpy(&color.ui, data, 64 / 8);496memset(&color.ui[2], 0, 64 / 8);497break;498case 32:499sf->format = PIPE_FORMAT_R32_UINT;500memcpy(&color.ui, data, 32 / 8);501memset(&color.ui[1], 0, 96 / 8);502break;503case 16:504sf->format = PIPE_FORMAT_R16_UINT;505color.ui[0] = util_cpu_to_le32(506util_le16_to_cpu(*(unsigned short *)data));507memset(&color.ui[1], 0, 96 / 8);508break;509case 8:510sf->format = PIPE_FORMAT_R8_UINT;511color.ui[0] = util_cpu_to_le32(*(unsigned char *)data);512memset(&color.ui[1], 0, 96 / 8);513break;514default:515assert(!"Unknown texel element size");516return;517}518519pipe->clear_render_target(pipe, sf, &color,520box->x, box->y, box->width, box->height, false);521}522pipe->surface_destroy(pipe, sf);523}524525void526nv50_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,527const union pipe_color_union *color,528double depth, unsigned stencil)529{530struct nv50_context *nv50 = nv50_context(pipe);531struct nouveau_pushbuf *push = nv50->base.pushbuf;532struct pipe_framebuffer_state *fb = &nv50->framebuffer;533unsigned i, j, k;534uint32_t mode = 0;535536/* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */537if (!nv50_state_validate_3d(nv50, NV50_NEW_3D_FRAMEBUFFER))538return;539540if (scissor_state) {541uint32_t minx = scissor_state->minx;542uint32_t maxx = MIN2(fb->width, scissor_state->maxx);543uint32_t miny = scissor_state->miny;544uint32_t maxy = MIN2(fb->height, scissor_state->maxy);545if (maxx <= minx || maxy <= miny)546return;547548BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);549PUSH_DATA (push, minx | (maxx - minx) << 16);550PUSH_DATA (push, miny | (maxy - miny) << 16);551}552553/* We have to clear ALL of the layers, not up to the min number of layers554* of any attachment. */555BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);556PUSH_DATA (push, (nv50->rt_array_mode & NV50_3D_RT_ARRAY_MODE_MODE_3D) | 512);557558if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {559BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4);560PUSH_DATAf(push, color->f[0]);561PUSH_DATAf(push, color->f[1]);562PUSH_DATAf(push, color->f[2]);563PUSH_DATAf(push, color->f[3]);564if (buffers & PIPE_CLEAR_COLOR0)565mode =566NV50_3D_CLEAR_BUFFERS_R | NV50_3D_CLEAR_BUFFERS_G |567NV50_3D_CLEAR_BUFFERS_B | NV50_3D_CLEAR_BUFFERS_A;568}569570if (buffers & PIPE_CLEAR_DEPTH) {571BEGIN_NV04(push, NV50_3D(CLEAR_DEPTH), 1);572PUSH_DATA (push, fui(depth));573mode |= NV50_3D_CLEAR_BUFFERS_Z;574}575576if (buffers & PIPE_CLEAR_STENCIL) {577BEGIN_NV04(push, NV50_3D(CLEAR_STENCIL), 1);578PUSH_DATA (push, stencil & 0xff);579mode |= NV50_3D_CLEAR_BUFFERS_S;580}581582if (mode) {583int zs_layers = 0, color0_layers = 0;584if (fb->cbufs[0] && (mode & 0x3c))585color0_layers = nv50_surface(fb->cbufs[0])->depth;586if (fb->zsbuf && (mode & ~0x3c))587zs_layers = nv50_surface(fb->zsbuf)->depth;588589for (j = 0; j < MIN2(zs_layers, color0_layers); j++) {590BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1);591PUSH_DATA(push, mode | (j << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));592}593for (k = j; k < zs_layers; k++) {594BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1);595PUSH_DATA(push, (mode & ~0x3c) | (k << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));596}597for (k = j; k < color0_layers; k++) {598BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1);599PUSH_DATA(push, (mode & 0x3c) | (k << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));600}601}602603for (i = 1; i < fb->nr_cbufs; i++) {604struct pipe_surface *sf = fb->cbufs[i];605if (!sf || !(buffers & (PIPE_CLEAR_COLOR0 << i)))606continue;607for (j = 0; j < nv50_surface(sf)->depth; j++) {608BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1);609PUSH_DATA (push, (i << 6) | 0x3c |610(j << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT));611}612}613614/* restore the array mode */615BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);616PUSH_DATA (push, nv50->rt_array_mode);617618/* restore screen scissor */619if (scissor_state) {620BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);621PUSH_DATA (push, fb->width << 16);622PUSH_DATA (push, fb->height << 16);623}624}625626static void627nv50_clear_buffer_push(struct pipe_context *pipe,628struct pipe_resource *res,629unsigned offset, unsigned size,630const void *data, int data_size)631{632struct nv50_context *nv50 = nv50_context(pipe);633struct nouveau_pushbuf *push = nv50->base.pushbuf;634struct nv04_resource *buf = nv04_resource(res);635unsigned count = (size + 3) / 4;636unsigned xcoord = offset & 0xff;637unsigned tmp, i;638639if (data_size == 1) {640tmp = *(unsigned char *)data;641tmp = (tmp << 24) | (tmp << 16) | (tmp << 8) | tmp;642data = &tmp;643data_size = 4;644} else if (data_size == 2) {645tmp = *(unsigned short *)data;646tmp = (tmp << 16) | tmp;647data = &tmp;648data_size = 4;649}650651unsigned data_words = data_size / 4;652653nouveau_bufctx_refn(nv50->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR);654nouveau_pushbuf_bufctx(push, nv50->bufctx);655nouveau_pushbuf_validate(push);656657offset &= ~0xff;658659BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);660PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);661PUSH_DATA (push, 1);662BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);663PUSH_DATA (push, 262144);664PUSH_DATA (push, 65536);665PUSH_DATA (push, 1);666PUSH_DATAh(push, buf->address + offset);667PUSH_DATA (push, buf->address + offset);668BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);669PUSH_DATA (push, 0);670PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);671BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);672PUSH_DATA (push, size);673PUSH_DATA (push, 1);674PUSH_DATA (push, 0);675PUSH_DATA (push, 1);676PUSH_DATA (push, 0);677PUSH_DATA (push, 1);678PUSH_DATA (push, 0);679PUSH_DATA (push, xcoord);680PUSH_DATA (push, 0);681PUSH_DATA (push, 0);682683while (count) {684unsigned nr_data = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN) / data_words;685unsigned nr = nr_data * data_words;686687BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr);688for (i = 0; i < nr_data; i++)689PUSH_DATAp(push, data, data_words);690691count -= nr;692}693694nv50_resource_validate(buf, NOUVEAU_BO_WR);695696nouveau_bufctx_reset(nv50->bufctx, 0);697}698699static void700nv50_clear_buffer(struct pipe_context *pipe,701struct pipe_resource *res,702unsigned offset, unsigned size,703const void *data, int data_size)704{705struct nv50_context *nv50 = nv50_context(pipe);706struct nouveau_pushbuf *push = nv50->base.pushbuf;707struct nv04_resource *buf = (struct nv04_resource *)res;708union pipe_color_union color;709enum pipe_format dst_fmt;710unsigned width, height, elements;711712assert(res->target == PIPE_BUFFER);713assert(nouveau_bo_memtype(buf->bo) == 0);714715switch (data_size) {716case 16:717dst_fmt = PIPE_FORMAT_R32G32B32A32_UINT;718memcpy(&color.ui, data, 16);719break;720case 8:721dst_fmt = PIPE_FORMAT_R32G32_UINT;722memcpy(&color.ui, data, 8);723memset(&color.ui[2], 0, 8);724break;725case 4:726dst_fmt = PIPE_FORMAT_R32_UINT;727memcpy(&color.ui, data, 4);728memset(&color.ui[1], 0, 12);729break;730case 2:731dst_fmt = PIPE_FORMAT_R16_UINT;732color.ui[0] = util_cpu_to_le32(733util_le16_to_cpu(*(unsigned short *)data));734memset(&color.ui[1], 0, 12);735break;736case 1:737dst_fmt = PIPE_FORMAT_R8_UINT;738color.ui[0] = util_cpu_to_le32(*(unsigned char *)data);739memset(&color.ui[1], 0, 12);740break;741default:742assert(!"Unsupported element size");743return;744}745746util_range_add(&buf->base, &buf->valid_buffer_range, offset, offset + size);747748assert(size % data_size == 0);749750if (offset & 0xff) {751unsigned fixup_size = MIN2(size, align(offset, 0x100) - offset);752assert(fixup_size % data_size == 0);753nv50_clear_buffer_push(pipe, res, offset, fixup_size, data, data_size);754offset += fixup_size;755size -= fixup_size;756if (!size)757return;758}759760elements = size / data_size;761height = (elements + 8191) / 8192;762width = elements / height;763if (height > 1)764width &= ~0xff;765assert(width > 0);766767BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4);768PUSH_DATA (push, color.ui[0]);769PUSH_DATA (push, color.ui[1]);770PUSH_DATA (push, color.ui[2]);771PUSH_DATA (push, color.ui[3]);772773if (nouveau_pushbuf_space(push, 64, 1, 0))774return;775776PUSH_REFN(push, buf->bo, buf->domain | NOUVEAU_BO_WR);777778BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);779PUSH_DATA (push, width << 16);780PUSH_DATA (push, height << 16);781BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);782PUSH_DATA (push, 8192 << 16);783PUSH_DATA (push, 8192 << 16);784nv50->scissors_dirty |= 1;785786BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);787PUSH_DATA (push, 1);788BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5);789PUSH_DATAh(push, buf->address + offset);790PUSH_DATA (push, buf->address + offset);791PUSH_DATA (push, nv50_format_table[dst_fmt].rt);792PUSH_DATA (push, 0);793PUSH_DATA (push, 0);794BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);795PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | align(width * data_size, 0x100));796PUSH_DATA (push, height);797BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);798PUSH_DATA (push, 0);799BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);800PUSH_DATA (push, 0);801802/* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */803804BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);805PUSH_DATA (push, (width << 16));806PUSH_DATA (push, (height << 16));807808BEGIN_NV04(push, NV50_3D(COND_MODE), 1);809PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);810811BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), 1);812PUSH_DATA (push, 0x3c);813814BEGIN_NV04(push, NV50_3D(COND_MODE), 1);815PUSH_DATA (push, nv50->cond_condmode);816817nv50_resource_validate(buf, NOUVEAU_BO_WR);818819if (width * height != elements) {820offset += width * height * data_size;821width = elements - width * height;822nv50_clear_buffer_push(pipe, res, offset, width * data_size,823data, data_size);824}825826nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_SCISSOR;827}828829/* =============================== BLIT CODE ===================================830*/831832struct nv50_blitter833{834struct nv50_program *fp[NV50_BLIT_MAX_TEXTURE_TYPES][NV50_BLIT_MODES];835struct nv50_program vp;836837struct nv50_tsc_entry sampler[2]; /* nearest, bilinear */838839mtx_t mutex;840};841842struct nv50_blitctx843{844struct nv50_context *nv50;845struct nv50_program *fp;846uint8_t mode;847uint16_t color_mask;848uint8_t filter;849uint8_t render_condition_enable;850enum pipe_texture_target target;851struct {852struct pipe_framebuffer_state fb;853struct nv50_window_rect_stateobj window_rect;854struct nv50_rasterizer_stateobj *rast;855struct nv50_program *vp;856struct nv50_program *gp;857struct nv50_program *fp;858unsigned num_textures[NV50_MAX_3D_SHADER_STAGES];859unsigned num_samplers[NV50_MAX_3D_SHADER_STAGES];860struct pipe_sampler_view *texture[2];861struct nv50_tsc_entry *sampler[2];862unsigned min_samples;863uint32_t dirty_3d;864} saved;865struct nv50_rasterizer_stateobj rast;866};867868static void869nv50_blitter_make_vp(struct nv50_blitter *blit)870{871static const uint32_t code[] =872{8730x10000001, 0x0423c788, /* mov b32 o[0x00] s[0x00] */ /* HPOS.x */8740x10000205, 0x0423c788, /* mov b32 o[0x04] s[0x04] */ /* HPOS.y */8750x10000409, 0x0423c788, /* mov b32 o[0x08] s[0x08] */ /* TEXC.x */8760x1000060d, 0x0423c788, /* mov b32 o[0x0c] s[0x0c] */ /* TEXC.y */8770x10000811, 0x0423c789, /* mov b32 o[0x10] s[0x10] */ /* TEXC.z */878};879880blit->vp.type = PIPE_SHADER_VERTEX;881blit->vp.translated = true;882blit->vp.code = (uint32_t *)code; /* const_cast */883blit->vp.code_size = sizeof(code);884blit->vp.max_gpr = 4;885blit->vp.max_out = 5;886blit->vp.out_nr = 2;887blit->vp.out[0].mask = 0x3;888blit->vp.out[0].sn = TGSI_SEMANTIC_POSITION;889blit->vp.out[1].hw = 2;890blit->vp.out[1].mask = 0x7;891blit->vp.out[1].sn = TGSI_SEMANTIC_GENERIC;892blit->vp.out[1].si = 0;893blit->vp.vp.attrs[0] = 0x73;894blit->vp.vp.psiz = 0x40;895blit->vp.vp.edgeflag = 0x40;896}897898void *899nv50_blitter_make_fp(struct pipe_context *pipe,900unsigned mode,901enum pipe_texture_target ptarg)902{903struct ureg_program *ureg;904struct ureg_src tc;905struct ureg_dst out;906struct ureg_dst data;907908const unsigned target = nv50_blit_get_tgsi_texture_target(ptarg);909910bool tex_rgbaz = false;911bool tex_s = false;912bool cvt_un8 = false;913914bool int_clamp = mode == NV50_BLIT_MODE_INT_CLAMP;915if (int_clamp)916mode = NV50_BLIT_MODE_PASS;917918if (mode != NV50_BLIT_MODE_PASS &&919mode != NV50_BLIT_MODE_Z24X8 &&920mode != NV50_BLIT_MODE_X8Z24)921tex_s = true;922923if (mode != NV50_BLIT_MODE_X24S8 &&924mode != NV50_BLIT_MODE_S8X24 &&925mode != NV50_BLIT_MODE_XS)926tex_rgbaz = true;927928if (mode != NV50_BLIT_MODE_PASS &&929mode != NV50_BLIT_MODE_ZS &&930mode != NV50_BLIT_MODE_XS)931cvt_un8 = true;932933ureg = ureg_create(PIPE_SHADER_FRAGMENT);934if (!ureg)935return NULL;936937out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);938tc = ureg_DECL_fs_input(939ureg, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_LINEAR);940941if (ptarg == PIPE_TEXTURE_1D_ARRAY) {942/* Adjust coordinates. Depth is in z, but TEX expects it to be in y. */943tc = ureg_swizzle(tc, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Z,944TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z);945}946947data = ureg_DECL_temporary(ureg);948949if (tex_s) {950ureg_TEX(ureg, ureg_writemask(data, TGSI_WRITEMASK_X),951target, tc, ureg_DECL_sampler(ureg, 1));952ureg_MOV(ureg, ureg_writemask(data, TGSI_WRITEMASK_Y),953ureg_scalar(ureg_src(data), TGSI_SWIZZLE_X));954}955if (tex_rgbaz) {956const unsigned mask = (mode == NV50_BLIT_MODE_PASS) ?957TGSI_WRITEMASK_XYZW : TGSI_WRITEMASK_X;958ureg_TEX(ureg, ureg_writemask(data, mask),959target, tc, ureg_DECL_sampler(ureg, 0));960}961962/* handle signed to unsigned integer conversions */963if (int_clamp)964ureg_UMIN(ureg, data, ureg_src(data), ureg_imm1u(ureg, 0x7fffffff));965966if (cvt_un8) {967struct ureg_src mask;968struct ureg_src scale;969struct ureg_dst outz;970struct ureg_dst outs;971struct ureg_dst zdst3 = ureg_writemask(data, TGSI_WRITEMASK_XYZ);972struct ureg_dst zdst = ureg_writemask(data, TGSI_WRITEMASK_X);973struct ureg_dst sdst = ureg_writemask(data, TGSI_WRITEMASK_Y);974struct ureg_src zsrc3 = ureg_src(data);975struct ureg_src zsrc = ureg_scalar(zsrc3, TGSI_SWIZZLE_X);976struct ureg_src ssrc = ureg_scalar(zsrc3, TGSI_SWIZZLE_Y);977struct ureg_src zshuf;978979mask = ureg_imm3u(ureg, 0x0000ff, 0x00ff00, 0xff0000);980scale = ureg_imm4f(ureg,9811.0f / 0x0000ff, 1.0f / 0x00ff00, 1.0f / 0xff0000,982(1 << 24) - 1);983984if (mode == NV50_BLIT_MODE_Z24S8 ||985mode == NV50_BLIT_MODE_X24S8 ||986mode == NV50_BLIT_MODE_Z24X8) {987outz = ureg_writemask(out, TGSI_WRITEMASK_XYZ);988outs = ureg_writemask(out, TGSI_WRITEMASK_W);989zshuf = ureg_src(data);990} else {991outz = ureg_writemask(out, TGSI_WRITEMASK_YZW);992outs = ureg_writemask(out, TGSI_WRITEMASK_X);993zshuf = ureg_swizzle(zsrc3, TGSI_SWIZZLE_W,994TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z);995}996997if (tex_s) {998ureg_I2F(ureg, sdst, ssrc);999ureg_MUL(ureg, outs, ssrc, ureg_scalar(scale, TGSI_SWIZZLE_X));1000}10011002if (tex_rgbaz) {1003ureg_MUL(ureg, zdst, zsrc, ureg_scalar(scale, TGSI_SWIZZLE_W));1004ureg_F2I(ureg, zdst, zsrc);1005ureg_AND(ureg, zdst3, zsrc, mask);1006ureg_I2F(ureg, zdst3, zsrc3);1007ureg_MUL(ureg, zdst3, zsrc3, scale);1008ureg_MOV(ureg, outz, zshuf);1009}1010} else {1011unsigned mask = TGSI_WRITEMASK_XYZW;10121013if (mode != NV50_BLIT_MODE_PASS) {1014mask &= ~TGSI_WRITEMASK_ZW;1015if (!tex_s)1016mask = TGSI_WRITEMASK_X;1017if (!tex_rgbaz)1018mask = TGSI_WRITEMASK_Y;1019}1020ureg_MOV(ureg, ureg_writemask(out, mask), ureg_src(data));1021}1022ureg_END(ureg);10231024return ureg_create_shader_and_destroy(ureg, pipe);1025}10261027static void1028nv50_blitter_make_sampler(struct nv50_blitter *blit)1029{1030/* clamp to edge, min/max lod = 0, nearest filtering */10311032blit->sampler[0].id = -1;10331034blit->sampler[0].tsc[0] = G80_TSC_0_SRGB_CONVERSION |1035(G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_U__SHIFT) |1036(G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_V__SHIFT) |1037(G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_P__SHIFT);1038blit->sampler[0].tsc[1] =1039G80_TSC_1_MAG_FILTER_NEAREST |1040G80_TSC_1_MIN_FILTER_NEAREST |1041G80_TSC_1_MIP_FILTER_NONE;10421043/* clamp to edge, min/max lod = 0, bilinear filtering */10441045blit->sampler[1].id = -1;10461047blit->sampler[1].tsc[0] = blit->sampler[0].tsc[0];1048blit->sampler[1].tsc[1] =1049G80_TSC_1_MAG_FILTER_LINEAR |1050G80_TSC_1_MIN_FILTER_LINEAR |1051G80_TSC_1_MIP_FILTER_NONE;1052}10531054unsigned1055nv50_blit_select_mode(const struct pipe_blit_info *info)1056{1057const unsigned mask = info->mask;10581059switch (info->dst.resource->format) {1060case PIPE_FORMAT_Z24_UNORM_S8_UINT:1061case PIPE_FORMAT_Z24X8_UNORM:1062case PIPE_FORMAT_X24S8_UINT:1063switch (mask & PIPE_MASK_ZS) {1064case PIPE_MASK_ZS: return NV50_BLIT_MODE_Z24S8;1065case PIPE_MASK_Z: return NV50_BLIT_MODE_Z24X8;1066default:1067return NV50_BLIT_MODE_X24S8;1068}1069case PIPE_FORMAT_S8_UINT_Z24_UNORM:1070case PIPE_FORMAT_X8Z24_UNORM:1071case PIPE_FORMAT_S8X24_UINT:1072switch (mask & PIPE_MASK_ZS) {1073case PIPE_MASK_ZS: return NV50_BLIT_MODE_S8Z24;1074case PIPE_MASK_Z: return NV50_BLIT_MODE_X8Z24;1075default:1076return NV50_BLIT_MODE_S8X24;1077}1078case PIPE_FORMAT_Z32_FLOAT:1079case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:1080case PIPE_FORMAT_X32_S8X24_UINT:1081switch (mask & PIPE_MASK_ZS) {1082case PIPE_MASK_ZS: return NV50_BLIT_MODE_ZS;1083case PIPE_MASK_Z: return NV50_BLIT_MODE_PASS;1084default:1085return NV50_BLIT_MODE_XS;1086}1087default:1088if (util_format_is_pure_uint(info->src.format) &&1089util_format_is_pure_sint(info->dst.format))1090return NV50_BLIT_MODE_INT_CLAMP;1091return NV50_BLIT_MODE_PASS;1092}1093}10941095static void1096nv50_blit_select_fp(struct nv50_blitctx *ctx, const struct pipe_blit_info *info)1097{1098struct nv50_blitter *blitter = ctx->nv50->screen->blitter;10991100const enum pipe_texture_target ptarg =1101nv50_blit_reinterpret_pipe_texture_target(info->src.resource->target);11021103const unsigned targ = nv50_blit_texture_type(ptarg);1104const unsigned mode = ctx->mode;11051106if (!blitter->fp[targ][mode]) {1107mtx_lock(&blitter->mutex);1108if (!blitter->fp[targ][mode])1109blitter->fp[targ][mode] =1110nv50_blitter_make_fp(&ctx->nv50->base.pipe, mode, ptarg);1111mtx_unlock(&blitter->mutex);1112}1113ctx->fp = blitter->fp[targ][mode];1114}11151116static void1117nv50_blit_set_dst(struct nv50_blitctx *ctx,1118struct pipe_resource *res, unsigned level, unsigned layer,1119enum pipe_format format)1120{1121struct nv50_context *nv50 = ctx->nv50;1122struct pipe_context *pipe = &nv50->base.pipe;1123struct pipe_surface templ;11241125if (util_format_is_depth_or_stencil(format))1126templ.format = nv50_blit_zeta_to_colour_format(format);1127else1128templ.format = format;11291130templ.u.tex.level = level;1131templ.u.tex.first_layer = templ.u.tex.last_layer = layer;11321133if (layer == -1) {1134templ.u.tex.first_layer = 0;1135templ.u.tex.last_layer =1136(res->target == PIPE_TEXTURE_3D ? res->depth0 : res->array_size) - 1;1137}11381139nv50->framebuffer.cbufs[0] = nv50_miptree_surface_new(pipe, res, &templ);1140nv50->framebuffer.nr_cbufs = 1;1141nv50->framebuffer.zsbuf = NULL;1142nv50->framebuffer.width = nv50->framebuffer.cbufs[0]->width;1143nv50->framebuffer.height = nv50->framebuffer.cbufs[0]->height;1144}11451146static void1147nv50_blit_set_src(struct nv50_blitctx *blit,1148struct pipe_resource *res, unsigned level, unsigned layer,1149enum pipe_format format, const uint8_t filter)1150{1151struct nv50_context *nv50 = blit->nv50;1152struct pipe_context *pipe = &nv50->base.pipe;1153struct pipe_sampler_view templ;1154uint32_t flags;1155enum pipe_texture_target target;11561157target = nv50_blit_reinterpret_pipe_texture_target(res->target);11581159templ.target = target;1160templ.format = format;1161templ.u.tex.first_level = templ.u.tex.last_level = level;1162templ.u.tex.first_layer = templ.u.tex.last_layer = layer;1163templ.swizzle_r = PIPE_SWIZZLE_X;1164templ.swizzle_g = PIPE_SWIZZLE_Y;1165templ.swizzle_b = PIPE_SWIZZLE_Z;1166templ.swizzle_a = PIPE_SWIZZLE_W;11671168if (layer == -1) {1169templ.u.tex.first_layer = 0;1170templ.u.tex.last_layer =1171(res->target == PIPE_TEXTURE_3D ? res->depth0 : res->array_size) - 1;1172}11731174flags = res->last_level ? 0 : NV50_TEXVIEW_SCALED_COORDS;1175flags |= NV50_TEXVIEW_ACCESS_RESOLVE;1176if (filter && res->nr_samples == 8)1177flags |= NV50_TEXVIEW_FILTER_MSAA8;11781179nv50->textures[NV50_SHADER_STAGE_FRAGMENT][0] = nv50_create_texture_view(1180pipe, res, &templ, flags);1181nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1] = NULL;11821183nv50->num_textures[NV50_SHADER_STAGE_VERTEX] = 0;1184nv50->num_textures[NV50_SHADER_STAGE_GEOMETRY] = 0;1185nv50->num_textures[NV50_SHADER_STAGE_FRAGMENT] = 1;11861187templ.format = nv50_zs_to_s_format(format);1188if (templ.format != res->format) {1189nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1] = nv50_create_texture_view(1190pipe, res, &templ, flags);1191nv50->num_textures[NV50_SHADER_STAGE_FRAGMENT] = 2;1192}1193}11941195static void1196nv50_blitctx_prepare_state(struct nv50_blitctx *blit)1197{1198struct nouveau_pushbuf *push = blit->nv50->base.pushbuf;11991200if (blit->nv50->cond_query && !blit->render_condition_enable) {1201BEGIN_NV04(push, NV50_3D(COND_MODE), 1);1202PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);1203}12041205/* blend state */1206BEGIN_NV04(push, NV50_3D(COLOR_MASK(0)), 1);1207PUSH_DATA (push, blit->color_mask);1208BEGIN_NV04(push, NV50_3D(BLEND_ENABLE(0)), 1);1209PUSH_DATA (push, 0);1210BEGIN_NV04(push, NV50_3D(LOGIC_OP_ENABLE), 1);1211PUSH_DATA (push, 0);12121213/* rasterizer state */1214#ifndef NV50_SCISSORS_CLIPPING1215BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(0)), 1);1216PUSH_DATA (push, 1);1217#endif1218BEGIN_NV04(push, NV50_3D(VERTEX_TWO_SIDE_ENABLE), 1);1219PUSH_DATA (push, 0);1220BEGIN_NV04(push, NV50_3D(FRAG_COLOR_CLAMP_EN), 1);1221PUSH_DATA (push, 0);1222BEGIN_NV04(push, NV50_3D(MULTISAMPLE_ENABLE), 1);1223PUSH_DATA (push, 0);1224BEGIN_NV04(push, NV50_3D(MSAA_MASK(0)), 4);1225PUSH_DATA (push, 0xffff);1226PUSH_DATA (push, 0xffff);1227PUSH_DATA (push, 0xffff);1228PUSH_DATA (push, 0xffff);1229BEGIN_NV04(push, NV50_3D(POLYGON_MODE_FRONT), 3);1230PUSH_DATA (push, NV50_3D_POLYGON_MODE_FRONT_FILL);1231PUSH_DATA (push, NV50_3D_POLYGON_MODE_BACK_FILL);1232PUSH_DATA (push, 0);1233BEGIN_NV04(push, NV50_3D(CULL_FACE_ENABLE), 1);1234PUSH_DATA (push, 0);1235BEGIN_NV04(push, NV50_3D(POLYGON_STIPPLE_ENABLE), 1);1236PUSH_DATA (push, 0);1237BEGIN_NV04(push, NV50_3D(POLYGON_OFFSET_FILL_ENABLE), 1);1238PUSH_DATA (push, 0);12391240/* zsa state */1241BEGIN_NV04(push, NV50_3D(DEPTH_TEST_ENABLE), 1);1242PUSH_DATA (push, 0);1243BEGIN_NV04(push, NV50_3D(DEPTH_BOUNDS_EN), 1);1244PUSH_DATA (push, 0);1245BEGIN_NV04(push, NV50_3D(STENCIL_ENABLE), 1);1246PUSH_DATA (push, 0);1247BEGIN_NV04(push, NV50_3D(ALPHA_TEST_ENABLE), 1);1248PUSH_DATA (push, 0);1249}12501251static void1252nv50_blitctx_pre_blit(struct nv50_blitctx *ctx,1253const struct pipe_blit_info *info)1254{1255struct nv50_context *nv50 = ctx->nv50;1256struct nv50_blitter *blitter = nv50->screen->blitter;1257int s;12581259ctx->saved.fb.width = nv50->framebuffer.width;1260ctx->saved.fb.height = nv50->framebuffer.height;1261ctx->saved.fb.nr_cbufs = nv50->framebuffer.nr_cbufs;1262ctx->saved.fb.cbufs[0] = nv50->framebuffer.cbufs[0];1263ctx->saved.fb.zsbuf = nv50->framebuffer.zsbuf;12641265ctx->saved.rast = nv50->rast;12661267ctx->saved.vp = nv50->vertprog;1268ctx->saved.gp = nv50->gmtyprog;1269ctx->saved.fp = nv50->fragprog;12701271ctx->saved.min_samples = nv50->min_samples;1272ctx->saved.window_rect = nv50->window_rect;12731274nv50->rast = &ctx->rast;12751276nv50->vertprog = &blitter->vp;1277nv50->gmtyprog = NULL;1278nv50->fragprog = ctx->fp;12791280nv50->window_rect.rects =1281MIN2(info->num_window_rectangles, NV50_MAX_WINDOW_RECTANGLES);1282nv50->window_rect.inclusive = info->window_rectangle_include;1283if (nv50->window_rect.rects)1284memcpy(nv50->window_rect.rect, info->window_rectangles,1285sizeof(struct pipe_scissor_state) * nv50->window_rect.rects);12861287for (s = 0; s < NV50_MAX_3D_SHADER_STAGES; ++s) {1288ctx->saved.num_textures[s] = nv50->num_textures[s];1289ctx->saved.num_samplers[s] = nv50->num_samplers[s];1290}1291ctx->saved.texture[0] = nv50->textures[NV50_SHADER_STAGE_FRAGMENT][0];1292ctx->saved.texture[1] = nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1];1293ctx->saved.sampler[0] = nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][0];1294ctx->saved.sampler[1] = nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][1];12951296nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][0] = &blitter->sampler[ctx->filter];1297nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][1] = &blitter->sampler[ctx->filter];12981299nv50->num_samplers[NV50_SHADER_STAGE_VERTEX] = 0;1300nv50->num_samplers[NV50_SHADER_STAGE_GEOMETRY] = 0;1301nv50->num_samplers[NV50_SHADER_STAGE_FRAGMENT] = 2;13021303nv50->min_samples = 1;13041305ctx->saved.dirty_3d = nv50->dirty_3d;13061307nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB);1308nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_TEXTURES);13091310nv50->dirty_3d =1311NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_MIN_SAMPLES |1312NV50_NEW_3D_VERTPROG | NV50_NEW_3D_FRAGPROG | NV50_NEW_3D_GMTYPROG |1313NV50_NEW_3D_TEXTURES | NV50_NEW_3D_SAMPLERS | NV50_NEW_3D_WINDOW_RECTS;1314}13151316static void1317nv50_blitctx_post_blit(struct nv50_blitctx *blit)1318{1319struct nv50_context *nv50 = blit->nv50;1320int s;13211322pipe_surface_reference(&nv50->framebuffer.cbufs[0], NULL);13231324nv50->framebuffer.width = blit->saved.fb.width;1325nv50->framebuffer.height = blit->saved.fb.height;1326nv50->framebuffer.nr_cbufs = blit->saved.fb.nr_cbufs;1327nv50->framebuffer.cbufs[0] = blit->saved.fb.cbufs[0];1328nv50->framebuffer.zsbuf = blit->saved.fb.zsbuf;13291330nv50->rast = blit->saved.rast;13311332nv50->vertprog = blit->saved.vp;1333nv50->gmtyprog = blit->saved.gp;1334nv50->fragprog = blit->saved.fp;13351336nv50->min_samples = blit->saved.min_samples;1337nv50->window_rect = blit->saved.window_rect;13381339pipe_sampler_view_reference(&nv50->textures[NV50_SHADER_STAGE_FRAGMENT][0], NULL);1340pipe_sampler_view_reference(&nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1], NULL);13411342for (s = 0; s < NV50_MAX_3D_SHADER_STAGES; ++s) {1343nv50->num_textures[s] = blit->saved.num_textures[s];1344nv50->num_samplers[s] = blit->saved.num_samplers[s];1345}1346nv50->textures[NV50_SHADER_STAGE_FRAGMENT][0] = blit->saved.texture[0];1347nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1] = blit->saved.texture[1];1348nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][0] = blit->saved.sampler[0];1349nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][1] = blit->saved.sampler[1];13501351if (nv50->cond_query && !blit->render_condition_enable)1352nv50->base.pipe.render_condition(&nv50->base.pipe, nv50->cond_query,1353nv50->cond_cond, nv50->cond_mode);13541355nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB);1356nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_TEXTURES);13571358nv50->dirty_3d = blit->saved.dirty_3d |1359(NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_SCISSOR | NV50_NEW_3D_SAMPLE_MASK |1360NV50_NEW_3D_RASTERIZER | NV50_NEW_3D_ZSA | NV50_NEW_3D_BLEND |1361NV50_NEW_3D_TEXTURES | NV50_NEW_3D_SAMPLERS | NV50_NEW_3D_WINDOW_RECTS |1362NV50_NEW_3D_VERTPROG | NV50_NEW_3D_GMTYPROG | NV50_NEW_3D_FRAGPROG);1363nv50->scissors_dirty |= 1;13641365nv50->base.pipe.set_min_samples(&nv50->base.pipe, blit->saved.min_samples);1366}136713681369static void1370nv50_blit_3d(struct nv50_context *nv50, const struct pipe_blit_info *info)1371{1372struct nv50_blitctx *blit = nv50->blit;1373struct nouveau_pushbuf *push = nv50->base.pushbuf;1374struct pipe_resource *src = info->src.resource;1375struct pipe_resource *dst = info->dst.resource;1376int32_t minx, maxx, miny, maxy;1377int32_t i;1378float x0, x1, y0, y1, z;1379float dz;1380float x_range, y_range;13811382blit->mode = nv50_blit_select_mode(info);1383blit->color_mask = nv50_blit_derive_color_mask(info);1384blit->filter = nv50_blit_get_filter(info);1385blit->render_condition_enable = info->render_condition_enable;13861387nv50_blit_select_fp(blit, info);1388nv50_blitctx_pre_blit(blit, info);13891390nv50_blit_set_dst(blit, dst, info->dst.level, -1, info->dst.format);1391nv50_blit_set_src(blit, src, info->src.level, -1, info->src.format,1392blit->filter);13931394nv50_blitctx_prepare_state(blit);13951396nv50_state_validate_3d(nv50, ~0);13971398/* When flipping a surface from zeta <-> color "mode", we have to wait for1399* the GPU to flush its current draws.1400*/1401struct nv50_miptree *mt = nv50_miptree(dst);1402bool serialize = util_format_is_depth_or_stencil(info->dst.format);1403if (serialize && mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {1404BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);1405PUSH_DATA (push, 0);1406}14071408x_range = (float)info->src.box.width / (float)info->dst.box.width;1409y_range = (float)info->src.box.height / (float)info->dst.box.height;14101411x0 = (float)info->src.box.x - x_range * (float)info->dst.box.x;1412y0 = (float)info->src.box.y - y_range * (float)info->dst.box.y;14131414x1 = x0 + 16384.0f * x_range;1415y1 = y0 + 16384.0f * y_range;14161417x0 *= (float)(1 << nv50_miptree(src)->ms_x);1418x1 *= (float)(1 << nv50_miptree(src)->ms_x);1419y0 *= (float)(1 << nv50_miptree(src)->ms_y);1420y1 *= (float)(1 << nv50_miptree(src)->ms_y);14211422/* XXX: multiply by 6 for cube arrays ? */1423dz = (float)info->src.box.depth / (float)info->dst.box.depth;1424z = (float)info->src.box.z;1425if (nv50_miptree(src)->layout_3d)1426z += 0.5f * dz;14271428if (src->last_level > 0) {1429/* If there are mip maps, GPU always assumes normalized coordinates. */1430const unsigned l = info->src.level;1431const float fh = u_minify(src->width0 << nv50_miptree(src)->ms_x, l);1432const float fv = u_minify(src->height0 << nv50_miptree(src)->ms_y, l);1433x0 /= fh;1434x1 /= fh;1435y0 /= fv;1436y1 /= fv;1437if (nv50_miptree(src)->layout_3d) {1438z /= u_minify(src->depth0, l);1439dz /= u_minify(src->depth0, l);1440}1441}14421443BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1);1444PUSH_DATA (push, 0);1445BEGIN_NV04(push, NV50_3D(VIEW_VOLUME_CLIP_CTRL), 1);1446PUSH_DATA (push, 0x1);14471448/* Draw a large triangle in screen coordinates covering the whole1449* render target, with scissors defining the destination region.1450* The vertex is supplied with non-normalized texture coordinates1451* arranged in a way to yield the desired offset and scale.1452*/14531454minx = info->dst.box.x;1455maxx = info->dst.box.x + info->dst.box.width;1456miny = info->dst.box.y;1457maxy = info->dst.box.y + info->dst.box.height;1458if (info->scissor_enable) {1459minx = MAX2(minx, info->scissor.minx);1460maxx = MIN2(maxx, info->scissor.maxx);1461miny = MAX2(miny, info->scissor.miny);1462maxy = MIN2(maxy, info->scissor.maxy);1463}1464BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);1465PUSH_DATA (push, (maxx << 16) | minx);1466PUSH_DATA (push, (maxy << 16) | miny);14671468for (i = 0; i < info->dst.box.depth; ++i, z += dz) {1469if (info->dst.box.z + i) {1470BEGIN_NV04(push, NV50_3D(LAYER), 1);1471PUSH_DATA (push, info->dst.box.z + i);1472}1473PUSH_SPACE(push, 32);1474BEGIN_NV04(push, NV50_3D(VERTEX_BEGIN_GL), 1);1475PUSH_DATA (push, NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES);1476BEGIN_NV04(push, NV50_3D(VTX_ATTR_3F_X(1)), 3);1477PUSH_DATAf(push, x0);1478PUSH_DATAf(push, y0);1479PUSH_DATAf(push, z);1480BEGIN_NV04(push, NV50_3D(VTX_ATTR_2F_X(0)), 2);1481PUSH_DATAf(push, 0.0f);1482PUSH_DATAf(push, 0.0f);1483BEGIN_NV04(push, NV50_3D(VTX_ATTR_3F_X(1)), 3);1484PUSH_DATAf(push, x1);1485PUSH_DATAf(push, y0);1486PUSH_DATAf(push, z);1487BEGIN_NV04(push, NV50_3D(VTX_ATTR_2F_X(0)), 2);1488PUSH_DATAf(push, 16384.0f);1489PUSH_DATAf(push, 0.0f);1490BEGIN_NV04(push, NV50_3D(VTX_ATTR_3F_X(1)), 3);1491PUSH_DATAf(push, x0);1492PUSH_DATAf(push, y1);1493PUSH_DATAf(push, z);1494BEGIN_NV04(push, NV50_3D(VTX_ATTR_2F_X(0)), 2);1495PUSH_DATAf(push, 0.0f);1496PUSH_DATAf(push, 16384.0f);1497BEGIN_NV04(push, NV50_3D(VERTEX_END_GL), 1);1498PUSH_DATA (push, 0);1499}1500if (info->dst.box.z + info->dst.box.depth - 1) {1501BEGIN_NV04(push, NV50_3D(LAYER), 1);1502PUSH_DATA (push, 0);1503}15041505/* re-enable normally constant state */15061507BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1);1508PUSH_DATA (push, 1);15091510/* mark the surface as reading, which will force a serialize next time it's1511* used for writing.1512*/1513if (serialize)1514mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_READING;15151516nv50_blitctx_post_blit(blit);1517}15181519static void1520nv50_blit_eng2d(struct nv50_context *nv50, const struct pipe_blit_info *info)1521{1522struct nouveau_pushbuf *push = nv50->base.pushbuf;1523struct nv50_miptree *dst = nv50_miptree(info->dst.resource);1524struct nv50_miptree *src = nv50_miptree(info->src.resource);1525const int32_t srcx_adj = info->src.box.width < 0 ? -1 : 0;1526const int32_t srcy_adj = info->src.box.height < 0 ? -1 : 0;1527const int32_t dz = info->dst.box.z;1528const int32_t sz = info->src.box.z;1529uint32_t dstw, dsth;1530int32_t dstx, dsty;1531int64_t srcx, srcy;1532int64_t du_dx, dv_dy;1533int i;1534uint32_t mode;1535uint32_t mask = nv50_blit_eng2d_get_mask(info);1536bool b;15371538mode = nv50_blit_get_filter(info) ?1539NV50_2D_BLIT_CONTROL_FILTER_BILINEAR :1540NV50_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE;1541mode |= (src->base.base.nr_samples > dst->base.base.nr_samples) ?1542NV50_2D_BLIT_CONTROL_ORIGIN_CORNER : NV50_2D_BLIT_CONTROL_ORIGIN_CENTER;15431544du_dx = ((int64_t)info->src.box.width << 32) / info->dst.box.width;1545dv_dy = ((int64_t)info->src.box.height << 32) / info->dst.box.height;15461547b = info->dst.format == info->src.format;1548nv50_2d_texture_set(push, 1, dst, info->dst.level, dz, info->dst.format, b);1549nv50_2d_texture_set(push, 0, src, info->src.level, sz, info->src.format, b);15501551if (info->scissor_enable) {1552BEGIN_NV04(push, NV50_2D(CLIP_X), 5);1553PUSH_DATA (push, info->scissor.minx << dst->ms_x);1554PUSH_DATA (push, info->scissor.miny << dst->ms_y);1555PUSH_DATA (push, (info->scissor.maxx - info->scissor.minx) << dst->ms_x);1556PUSH_DATA (push, (info->scissor.maxy - info->scissor.miny) << dst->ms_y);1557PUSH_DATA (push, 1); /* enable */1558}15591560if (nv50->cond_query && info->render_condition_enable) {1561BEGIN_NV04(push, NV50_2D(COND_MODE), 1);1562PUSH_DATA (push, nv50->cond_condmode);1563}15641565if (mask != 0xffffffff) {1566BEGIN_NV04(push, NV50_2D(ROP), 1);1567PUSH_DATA (push, 0xca); /* DPSDxax */1568BEGIN_NV04(push, NV50_2D(PATTERN_COLOR_FORMAT), 1);1569PUSH_DATA (push, NV50_2D_PATTERN_COLOR_FORMAT_A8R8G8B8);1570BEGIN_NV04(push, NV50_2D(PATTERN_BITMAP_COLOR(0)), 4);1571PUSH_DATA (push, 0x00000000);1572PUSH_DATA (push, mask);1573PUSH_DATA (push, 0xffffffff);1574PUSH_DATA (push, 0xffffffff);1575BEGIN_NV04(push, NV50_2D(OPERATION), 1);1576PUSH_DATA (push, NV50_2D_OPERATION_ROP);1577} else1578if (info->src.format != info->dst.format) {1579if (info->src.format == PIPE_FORMAT_R8_UNORM ||1580info->src.format == PIPE_FORMAT_R16_UNORM ||1581info->src.format == PIPE_FORMAT_R16_FLOAT ||1582info->src.format == PIPE_FORMAT_R32_FLOAT) {1583mask = 0xffff0000; /* also makes condition for OPERATION reset true */1584BEGIN_NV04(push, NV50_2D(BETA4), 2);1585PUSH_DATA (push, mask);1586PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY_PREMULT);1587}1588}15891590if (src->ms_x > dst->ms_x || src->ms_y > dst->ms_y) {1591/* ms_x is always >= ms_y */1592du_dx <<= src->ms_x - dst->ms_x;1593dv_dy <<= src->ms_y - dst->ms_y;1594} else {1595du_dx >>= dst->ms_x - src->ms_x;1596dv_dy >>= dst->ms_y - src->ms_y;1597}15981599srcx = (int64_t)(info->src.box.x + srcx_adj) << (src->ms_x + 32);1600srcy = (int64_t)(info->src.box.y + srcy_adj) << (src->ms_y + 32);16011602if (src->base.base.nr_samples > dst->base.base.nr_samples) {1603/* center src coorinates for proper MS resolve filtering */1604srcx += (int64_t)1 << (src->ms_x + 31);1605srcy += (int64_t)1 << (src->ms_y + 31);1606}16071608dstx = info->dst.box.x << dst->ms_x;1609dsty = info->dst.box.y << dst->ms_y;16101611dstw = info->dst.box.width << dst->ms_x;1612dsth = info->dst.box.height << dst->ms_y;16131614if (dstx < 0) {1615dstw += dstx;1616srcx -= du_dx * dstx;1617dstx = 0;1618}1619if (dsty < 0) {1620dsth += dsty;1621srcy -= dv_dy * dsty;1622dsty = 0;1623}16241625BEGIN_NV04(push, NV50_2D(BLIT_CONTROL), 1);1626PUSH_DATA (push, mode);1627BEGIN_NV04(push, NV50_2D(BLIT_DST_X), 4);1628PUSH_DATA (push, dstx);1629PUSH_DATA (push, dsty);1630PUSH_DATA (push, dstw);1631PUSH_DATA (push, dsth);1632BEGIN_NV04(push, NV50_2D(BLIT_DU_DX_FRACT), 4);1633PUSH_DATA (push, du_dx);1634PUSH_DATA (push, du_dx >> 32);1635PUSH_DATA (push, dv_dy);1636PUSH_DATA (push, dv_dy >> 32);16371638BCTX_REFN(nv50->bufctx, 2D, &dst->base, WR);1639BCTX_REFN(nv50->bufctx, 2D, &src->base, RD);1640nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx);1641if (nouveau_pushbuf_validate(nv50->base.pushbuf))1642return;16431644for (i = 0; i < info->dst.box.depth; ++i) {1645if (i > 0) {1646/* no scaling in z-direction possible for eng2d blits */1647if (dst->layout_3d) {1648BEGIN_NV04(push, NV50_2D(DST_LAYER), 1);1649PUSH_DATA (push, info->dst.box.z + i);1650} else {1651const unsigned z = info->dst.box.z + i;1652const uint64_t address = dst->base.address +1653dst->level[info->dst.level].offset +1654z * dst->layer_stride;1655BEGIN_NV04(push, NV50_2D(DST_ADDRESS_HIGH), 2);1656PUSH_DATAh(push, address);1657PUSH_DATA (push, address);1658}1659if (src->layout_3d) {1660/* not possible because of depth tiling */1661assert(0);1662} else {1663const unsigned z = info->src.box.z + i;1664const uint64_t address = src->base.address +1665src->level[info->src.level].offset +1666z * src->layer_stride;1667BEGIN_NV04(push, NV50_2D(SRC_ADDRESS_HIGH), 2);1668PUSH_DATAh(push, address);1669PUSH_DATA (push, address);1670}1671BEGIN_NV04(push, NV50_2D(BLIT_SRC_Y_INT), 1); /* trigger */1672PUSH_DATA (push, srcy >> 32);1673} else {1674BEGIN_NV04(push, NV50_2D(BLIT_SRC_X_FRACT), 4);1675PUSH_DATA (push, srcx);1676PUSH_DATA (push, srcx >> 32);1677PUSH_DATA (push, srcy);1678PUSH_DATA (push, srcy >> 32);1679}1680}1681nv50_bufctx_fence(nv50->bufctx, false);16821683nouveau_bufctx_reset(nv50->bufctx, NV50_BIND_2D);16841685if (info->scissor_enable) {1686BEGIN_NV04(push, NV50_2D(CLIP_ENABLE), 1);1687PUSH_DATA (push, 0);1688}1689if (mask != 0xffffffff) {1690BEGIN_NV04(push, NV50_2D(OPERATION), 1);1691PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY);1692}1693if (nv50->cond_query && info->render_condition_enable) {1694BEGIN_NV04(push, NV50_2D(COND_MODE), 1);1695PUSH_DATA (push, NV50_2D_COND_MODE_ALWAYS);1696}1697}16981699static void1700nv50_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)1701{1702struct nv50_context *nv50 = nv50_context(pipe);1703struct nouveau_pushbuf *push = nv50->base.pushbuf;1704bool eng3d = FALSE;17051706if (info->src.box.width == 0 || info->src.box.height == 0 ||1707info->dst.box.width == 0 || info->dst.box.height == 0) {1708pipe_debug_message(&nv50->base.debug, ERROR,1709"Blit with zero-size src or dst box");1710return;1711}17121713if (util_format_is_depth_or_stencil(info->dst.resource->format)) {1714if (!(info->mask & PIPE_MASK_ZS))1715return;1716if (info->dst.resource->format == PIPE_FORMAT_Z32_FLOAT ||1717info->dst.resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)1718eng3d = true;1719if (info->filter != PIPE_TEX_FILTER_NEAREST)1720eng3d = true;1721} else {1722if (!(info->mask & PIPE_MASK_RGBA))1723return;1724if (info->mask != PIPE_MASK_RGBA)1725eng3d = true;1726}17271728if (nv50_miptree(info->src.resource)->layout_3d) {1729eng3d = true;1730} else1731if (info->src.box.depth != info->dst.box.depth) {1732eng3d = true;1733debug_printf("blit: cannot filter array or cube textures in z direction");1734}17351736if (!eng3d && info->dst.format != info->src.format) {1737if (!nv50_2d_dst_format_faithful(info->dst.format) ||1738!nv50_2d_src_format_faithful(info->src.format)) {1739eng3d = true;1740} else1741if (!nv50_2d_src_format_faithful(info->src.format)) {1742if (!util_format_is_luminance(info->src.format)) {1743if (util_format_is_intensity(info->src.format))1744eng3d = true;1745else1746if (!nv50_2d_dst_format_ops_supported(info->dst.format))1747eng3d = true;1748else1749eng3d = !nv50_2d_format_supported(info->src.format);1750}1751} else1752if (util_format_is_luminance_alpha(info->src.format))1753eng3d = true;1754}17551756if (info->src.resource->nr_samples == 8 &&1757info->dst.resource->nr_samples <= 1)1758eng3d = true;17591760if (info->num_window_rectangles > 0 || info->window_rectangle_include)1761eng3d = true;17621763/* FIXME: can't make this work with eng2d anymore */1764if ((info->src.resource->nr_samples | 1) !=1765(info->dst.resource->nr_samples | 1))1766eng3d = true;17671768/* FIXME: find correct src coordinate adjustments */1769if ((info->src.box.width != info->dst.box.width &&1770info->src.box.width != -info->dst.box.width) ||1771(info->src.box.height != info->dst.box.height &&1772info->src.box.height != -info->dst.box.height))1773eng3d = true;17741775if (nv50->screen->num_occlusion_queries_active) {1776BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1);1777PUSH_DATA (push, 0);1778}17791780if (!eng3d)1781nv50_blit_eng2d(nv50, info);1782else1783nv50_blit_3d(nv50, info);17841785if (nv50->screen->num_occlusion_queries_active) {1786BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1);1787PUSH_DATA (push, 1);1788}1789}17901791static void1792nv50_flush_resource(struct pipe_context *ctx,1793struct pipe_resource *resource)1794{1795}17961797bool1798nv50_blitter_create(struct nv50_screen *screen)1799{1800screen->blitter = CALLOC_STRUCT(nv50_blitter);1801if (!screen->blitter) {1802NOUVEAU_ERR("failed to allocate blitter struct\n");1803return false;1804}18051806(void) mtx_init(&screen->blitter->mutex, mtx_plain);18071808nv50_blitter_make_vp(screen->blitter);1809nv50_blitter_make_sampler(screen->blitter);18101811return true;1812}18131814void1815nv50_blitter_destroy(struct nv50_screen *screen)1816{1817struct nv50_blitter *blitter = screen->blitter;1818unsigned i, m;18191820for (i = 0; i < NV50_BLIT_MAX_TEXTURE_TYPES; ++i) {1821for (m = 0; m < NV50_BLIT_MODES; ++m) {1822struct nv50_program *prog = blitter->fp[i][m];1823if (prog) {1824nv50_program_destroy(NULL, prog);1825FREE((void *)prog->pipe.tokens);1826FREE(prog);1827}1828}1829}18301831mtx_destroy(&blitter->mutex);1832FREE(blitter);1833}18341835bool1836nv50_blitctx_create(struct nv50_context *nv50)1837{1838nv50->blit = CALLOC_STRUCT(nv50_blitctx);1839if (!nv50->blit) {1840NOUVEAU_ERR("failed to allocate blit context\n");1841return false;1842}18431844nv50->blit->nv50 = nv50;18451846nv50->blit->rast.pipe.half_pixel_center = 1;18471848return true;1849}18501851void1852nv50_init_surface_functions(struct nv50_context *nv50)1853{1854struct pipe_context *pipe = &nv50->base.pipe;18551856pipe->resource_copy_region = nv50_resource_copy_region;1857pipe->blit = nv50_blit;1858pipe->flush_resource = nv50_flush_resource;1859pipe->clear_texture = nv50_clear_texture;1860pipe->clear_render_target = nv50_clear_render_target;1861pipe->clear_depth_stencil = nv50_clear_depth_stencil;1862pipe->clear_buffer = nv50_clear_buffer;1863}186418651866