1/* 2 * Copyright 2012 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 * 24 */ 25 26#include "pipe/p_defines.h" 27#include "util/u_pack_color.h" 28 29#include "nouveau_gldefs.h" 30#include "nv_object.xml.h" 31#include "nv30/nv30-40_3d.xml.h" 32#include "nv30/nv30_context.h" 33#include "nv30/nv30_format.h" 34 35static inline uint32_t 36pack_rgba(enum pipe_format format, const float *rgba) 37{ 38 union util_color uc; 39 util_pack_color(rgba, format, &uc); 40 return uc.ui[0]; 41} 42 43static inline uint32_t 44pack_zeta(enum pipe_format format, double depth, unsigned stencil) 45{ 46 uint32_t zuint = (uint32_t)(depth * 4294967295.0); 47 if (format != PIPE_FORMAT_Z16_UNORM) 48 return (zuint & 0xffffff00) | (stencil & 0xff); 49 return zuint >> 16; 50} 51 52static void 53nv30_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state, 54 const union pipe_color_union *color, double depth, unsigned stencil) 55{ 56 struct nv30_context *nv30 = nv30_context(pipe); 57 struct nouveau_pushbuf *push = nv30->base.pushbuf; 58 struct pipe_framebuffer_state *fb = &nv30->framebuffer; 59 uint32_t colr = 0, zeta = 0, mode = 0; 60 61 if (!nv30_state_validate(nv30, NV30_NEW_FRAMEBUFFER, true)) 62 return; 63 64 if (scissor_state) { 65 uint32_t minx = scissor_state->minx; 66 uint32_t maxx = MIN2(fb->width, scissor_state->maxx); 67 uint32_t miny = scissor_state->miny; 68 uint32_t maxy = MIN2(fb->height, scissor_state->maxy); 69 70 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); 71 PUSH_DATA (push, minx | (maxx - minx) << 16); 72 PUSH_DATA (push, miny | (maxy - miny) << 16); 73 } 74 else { 75 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); 76 PUSH_DATA (push, 0x10000000); 77 PUSH_DATA (push, 0x10000000); 78 } 79 80 if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { 81 colr = pack_rgba(fb->cbufs[0]->format, color->f); 82 mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R | 83 NV30_3D_CLEAR_BUFFERS_COLOR_G | 84 NV30_3D_CLEAR_BUFFERS_COLOR_B | 85 NV30_3D_CLEAR_BUFFERS_COLOR_A; 86 } 87 88 if (fb->zsbuf) { 89 zeta = pack_zeta(fb->zsbuf->format, depth, stencil); 90 if (buffers & PIPE_CLEAR_DEPTH) 91 mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; 92 if (buffers & PIPE_CLEAR_STENCIL) { 93 mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; 94 BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 2); 95 PUSH_DATA (push, 0); 96 PUSH_DATA (push, 0x000000ff); 97 nv30->dirty |= NV30_NEW_ZSA; 98 } 99 } 100 101 /*XXX: wtf? fixes clears sometimes not clearing on nv3x... */ 102 if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) { 103 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3); 104 PUSH_DATA (push, zeta); 105 PUSH_DATA (push, colr); 106 PUSH_DATA (push, mode); 107 } 108 109 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3); 110 PUSH_DATA (push, zeta); 111 PUSH_DATA (push, colr); 112 PUSH_DATA (push, mode); 113 114 nv30_state_release(nv30); 115 116 /* Make sure regular draw commands will get their scissor state set */ 117 nv30->dirty |= NV30_NEW_SCISSOR; 118 nv30->state.scissor_off = 0; 119} 120 121static void 122nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, 123 const union pipe_color_union *color, 124 unsigned x, unsigned y, unsigned w, unsigned h, 125 bool render_condition_enabled) 126{ 127 struct nv30_context *nv30 = nv30_context(pipe); 128 struct nv30_surface *sf = nv30_surface(ps); 129 struct nv30_miptree *mt = nv30_miptree(ps->texture); 130 struct nouveau_pushbuf *push = nv30->base.pushbuf; 131 struct nouveau_object *eng3d = nv30->screen->eng3d; 132 struct nouveau_pushbuf_refn refn; 133 uint32_t rt_format; 134 135 rt_format = nv30_format(pipe->screen, ps->format)->hw; 136 if (util_format_get_blocksize(ps->format) == 4) 137 rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8; 138 else 139 rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16; 140 141 if (nv30_miptree(ps->texture)->swizzled) { 142 rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; 143 rt_format |= util_logbase2(sf->width) << 16; 144 rt_format |= util_logbase2(sf->height) << 24; 145 } else { 146 rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; 147 } 148 149 refn.bo = mt->base.bo; 150 refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; 151 if (nouveau_pushbuf_space(push, 32, 1, 0) || 152 nouveau_pushbuf_refn (push, &refn, 1)) 153 return; 154 155 BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); 156 PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0); 157 BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); 158 PUSH_DATA (push, sf->width << 16); 159 PUSH_DATA (push, sf->height << 16); 160 PUSH_DATA (push, rt_format); 161 BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2); 162 if (eng3d->oclass < NV40_3D_CLASS) 163 PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); 164 else 165 PUSH_DATA (push, sf->pitch); 166 PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); 167 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); 168 PUSH_DATA (push, (w << 16) | x); 169 PUSH_DATA (push, (h << 16) | y); 170 171 BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2); 172 PUSH_DATA (push, pack_rgba(ps->format, color->f)); 173 PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R | 174 NV30_3D_CLEAR_BUFFERS_COLOR_G | 175 NV30_3D_CLEAR_BUFFERS_COLOR_B | 176 NV30_3D_CLEAR_BUFFERS_COLOR_A); 177 178 nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; 179 nv30->state.scissor_off = 0; 180} 181 182static void 183nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps, 184 unsigned buffers, double depth, unsigned stencil, 185 unsigned x, unsigned y, unsigned w, unsigned h, 186 bool render_condition_enabled) 187{ 188 struct nv30_context *nv30 = nv30_context(pipe); 189 struct nv30_surface *sf = nv30_surface(ps); 190 struct nv30_miptree *mt = nv30_miptree(ps->texture); 191 struct nouveau_pushbuf *push = nv30->base.pushbuf; 192 struct nouveau_object *eng3d = nv30->screen->eng3d; 193 struct nouveau_pushbuf_refn refn; 194 uint32_t rt_format, mode = 0; 195 196 rt_format = nv30_format(pipe->screen, ps->format)->hw; 197 if (util_format_get_blocksize(ps->format) == 4) 198 rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8; 199 else 200 rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5; 201 202 if (nv30_miptree(ps->texture)->swizzled) { 203 rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; 204 rt_format |= util_logbase2(sf->width) << 16; 205 rt_format |= util_logbase2(sf->height) << 24; 206 } else { 207 rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; 208 } 209 210 if (buffers & PIPE_CLEAR_DEPTH) 211 mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; 212 if (buffers & PIPE_CLEAR_STENCIL) 213 mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; 214 215 refn.bo = mt->base.bo; 216 refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; 217 if (nouveau_pushbuf_space(push, 32, 1, 0) || 218 nouveau_pushbuf_refn (push, &refn, 1)) 219 return; 220 221 BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); 222 PUSH_DATA (push, 0); 223 BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); 224 PUSH_DATA (push, sf->width << 16); 225 PUSH_DATA (push, sf->height << 16); 226 PUSH_DATA (push, rt_format); 227 if (eng3d->oclass < NV40_3D_CLASS) { 228 BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1); 229 PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); 230 } else { 231 BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1); 232 PUSH_DATA (push, sf->pitch); 233 } 234 BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1); 235 PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); 236 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); 237 PUSH_DATA (push, (w << 16) | x); 238 PUSH_DATA (push, (h << 16) | y); 239 240 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1); 241 PUSH_DATA (push, pack_zeta(ps->format, depth, stencil)); 242 BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1); 243 PUSH_DATA (push, mode); 244 245 nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; 246 nv30->state.scissor_off = 0; 247} 248 249void 250nv30_clear_init(struct pipe_context *pipe) 251{ 252 pipe->clear = nv30_clear; 253 pipe->clear_render_target = nv30_clear_render_target; 254 pipe->clear_depth_stencil = nv30_clear_depth_stencil; 255} 256