X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fnv30%2Fnv30_clear.c;h=8992de31d09508508b81c35ab1821d0ae67663f6;hb=5bbeae7a3d3be17d44b1bc851872a107a75c393b;hp=8c3ca204d586912aa2ce86735a00bdcd6186e0b0;hpb=8cd046c9b1da31e4ff178816bdfe2ee3451a1553;p=mesa.git diff --git a/src/gallium/drivers/nv30/nv30_clear.c b/src/gallium/drivers/nv30/nv30_clear.c index 8c3ca204d58..8992de31d09 100644 --- a/src/gallium/drivers/nv30/nv30_clear.c +++ b/src/gallium/drivers/nv30/nv30_clear.c @@ -1,13 +1,226 @@ -#include "pipe/p_context.h" +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + * + */ + #include "pipe/p_defines.h" -#include "pipe/p_state.h" +#include "util/u_pack_color.h" +#include "nouveau/nouveau_gldefs.h" +#include "nouveau/nv_object.xml.h" +#include "nv30-40_3d.xml.h" #include "nv30_context.h" +#include "nv30_format.h" + +static INLINE uint32_t +pack_rgba(enum pipe_format format, const float *rgba) +{ + union util_color uc; + util_pack_color(rgba, format, &uc); + return uc.ui; +} + +static INLINE uint32_t +pack_zeta(enum pipe_format format, double depth, unsigned stencil) +{ + uint32_t zuint = (uint32_t)(depth * 4294967295.0); + if (format != PIPE_FORMAT_Z16_UNORM) + return (zuint & 0xffffff00) | (stencil & 0xff); + return zuint >> 16; +} + +static void +nv30_clear(struct pipe_context *pipe, unsigned buffers, + const union pipe_color_union *color, double depth, unsigned stencil) +{ + struct nv30_context *nv30 = nv30_context(pipe); + struct nouveau_pushbuf *push = nv30->base.pushbuf; + struct pipe_framebuffer_state *fb = &nv30->framebuffer; + uint32_t colr = 0, zeta = 0, mode = 0; + + if (!nv30_state_validate(nv30, TRUE)) + return; + + if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { + colr = pack_rgba(fb->cbufs[0]->format, color->f); + mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R | + NV30_3D_CLEAR_BUFFERS_COLOR_G | + NV30_3D_CLEAR_BUFFERS_COLOR_B | + NV30_3D_CLEAR_BUFFERS_COLOR_A; + } + + if (fb->zsbuf) { + zeta = pack_zeta(fb->zsbuf->format, depth, stencil); + if (buffers & PIPE_CLEAR_DEPTH) + mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; + if (buffers & PIPE_CLEAR_STENCIL) + mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; + } + + /*XXX: wtf? fixes clears sometimes not clearing on nv3x... */ + if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) { + BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3); + PUSH_DATA (push, zeta); + PUSH_DATA (push, colr); + PUSH_DATA (push, mode); + } + + BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3); + PUSH_DATA (push, zeta); + PUSH_DATA (push, colr); + PUSH_DATA (push, mode); + + nv30_state_release(nv30); +} + +static void +nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, + const union pipe_color_union *color, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv30_context *nv30 = nv30_context(pipe); + struct nv30_surface *sf = nv30_surface(ps); + struct nv30_miptree *mt = nv30_miptree(ps->texture); + struct nouveau_pushbuf *push = nv30->base.pushbuf; + struct nouveau_object *eng3d = nv30->screen->eng3d; + struct nouveau_pushbuf_refn refn; + uint32_t rt_format; + + rt_format = nv30_format(pipe->screen, ps->format)->hw; + if (util_format_get_blocksize(ps->format) == 4) + rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8; + else + rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16; + + if (nv30_miptree(ps->texture)->swizzled) { + rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; + rt_format |= util_logbase2(sf->width) << 16; + rt_format |= util_logbase2(sf->height) << 24; + } else { + rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; + } + + refn.bo = mt->base.bo; + refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; + if (nouveau_pushbuf_space(push, 16, 1, 0) || + nouveau_pushbuf_refn (push, &refn, 1)) + return; + + BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); + PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0); + BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); + PUSH_DATA (push, sf->width << 16); + PUSH_DATA (push, sf->height << 16); + PUSH_DATA (push, rt_format); + BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2); + if (eng3d->oclass < NV40_3D_CLASS) + PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); + else + PUSH_DATA (push, sf->pitch); + PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); + BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); + PUSH_DATA (push, (w << 16) | x); + PUSH_DATA (push, (h << 16) | y); + + BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2); + PUSH_DATA (push, pack_rgba(ps->format, color->f)); + PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R | + NV30_3D_CLEAR_BUFFERS_COLOR_G | + NV30_3D_CLEAR_BUFFERS_COLOR_B | + NV30_3D_CLEAR_BUFFERS_COLOR_A); + + nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; +} + +static void +nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps, + unsigned buffers, double depth, unsigned stencil, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv30_context *nv30 = nv30_context(pipe); + struct nv30_surface *sf = nv30_surface(ps); + struct nv30_miptree *mt = nv30_miptree(ps->texture); + struct nouveau_pushbuf *push = nv30->base.pushbuf; + struct nouveau_object *eng3d = nv30->screen->eng3d; + struct nouveau_pushbuf_refn refn; + uint32_t rt_format, mode = 0; + + rt_format = nv30_format(pipe->screen, ps->format)->hw; + if (util_format_get_blocksize(ps->format) == 4) + rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8; + else + rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5; + + if (nv30_miptree(ps->texture)->swizzled) { + rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; + rt_format |= util_logbase2(sf->width) << 16; + rt_format |= util_logbase2(sf->height) << 24; + } else { + rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; + } + + if (buffers & PIPE_CLEAR_DEPTH) + mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; + if (buffers & PIPE_CLEAR_STENCIL) + mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; + + refn.bo = mt->base.bo; + refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; + if (nouveau_pushbuf_space(push, 32, 1, 0) || + nouveau_pushbuf_refn (push, &refn, 1)) + return; + + BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); + PUSH_DATA (push, 0); + BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); + PUSH_DATA (push, sf->width << 16); + PUSH_DATA (push, sf->height << 16); + PUSH_DATA (push, rt_format); + if (eng3d->oclass < NV40_3D_CLASS) { + BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1); + PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); + } else { + BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1); + PUSH_DATA (push, sf->pitch); + } + BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1); + PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); + BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); + PUSH_DATA (push, (w << 16) | x); + PUSH_DATA (push, (h << 16) | y); + + BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1); + PUSH_DATA (push, pack_zeta(ps->format, depth, stencil)); + BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1); + PUSH_DATA (push, mode); + + nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; +} void -nv30_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue) +nv30_clear_init(struct pipe_context *pipe) { - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); - ps->status = PIPE_SURFACE_STATUS_CLEAR; + pipe->clear = nv30_clear; + pipe->clear_render_target = nv30_clear_render_target; + pipe->clear_depth_stencil = nv30_clear_depth_stencil; }