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 35 static inline uint32_t 36 pack_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 43 static inline uint32_t 44 pack_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 52 static void 53 nv30_clear(struct pipe_context *pipe, unsigned buffers, 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 | NV30_NEW_SCISSOR, true)) 62 return; 63 64 if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { 65 colr = pack_rgba(fb->cbufs[0]->format, color->f); 66 mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R | 67 NV30_3D_CLEAR_BUFFERS_COLOR_G | 68 NV30_3D_CLEAR_BUFFERS_COLOR_B | 69 NV30_3D_CLEAR_BUFFERS_COLOR_A; 70 } 71 72 if (fb->zsbuf) { 73 zeta = pack_zeta(fb->zsbuf->format, depth, stencil); 74 if (buffers & PIPE_CLEAR_DEPTH) 75 mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; 76 if (buffers & PIPE_CLEAR_STENCIL) { 77 mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; 78 BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 2); 79 PUSH_DATA (push, 0); 80 PUSH_DATA (push, 0x000000ff); 81 nv30->dirty |= NV30_NEW_ZSA; 82 } 83 } 84 85 /*XXX: wtf? fixes clears sometimes not clearing on nv3x... */ 86 if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) { 87 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3); 88 PUSH_DATA (push, zeta); 89 PUSH_DATA (push, colr); 90 PUSH_DATA (push, mode); 91 } 92 93 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3); 94 PUSH_DATA (push, zeta); 95 PUSH_DATA (push, colr); 96 PUSH_DATA (push, mode); 97 98 nv30_state_release(nv30); 99 } 100 101 static void 102 nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, 103 const union pipe_color_union *color, 104 unsigned x, unsigned y, unsigned w, unsigned h, 105 bool render_condition_enabled) 106 { 107 struct nv30_context *nv30 = nv30_context(pipe); 108 struct nv30_surface *sf = nv30_surface(ps); 109 struct nv30_miptree *mt = nv30_miptree(ps->texture); 110 struct nouveau_pushbuf *push = nv30->base.pushbuf; 111 struct nouveau_object *eng3d = nv30->screen->eng3d; 112 struct nouveau_pushbuf_refn refn; 113 uint32_t rt_format; 114 115 rt_format = nv30_format(pipe->screen, ps->format)->hw; 116 if (util_format_get_blocksize(ps->format) == 4) 117 rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8; 118 else 119 rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16; 120 121 if (nv30_miptree(ps->texture)->swizzled) { 122 rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; 123 rt_format |= util_logbase2(sf->width) << 16; 124 rt_format |= util_logbase2(sf->height) << 24; 125 } else { 126 rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; 127 } 128 129 refn.bo = mt->base.bo; 130 refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; 131 if (nouveau_pushbuf_space(push, 32, 1, 0) || 132 nouveau_pushbuf_refn (push, &refn, 1)) 133 return; 134 135 BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); 136 PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0); 137 BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); 138 PUSH_DATA (push, sf->width << 16); 139 PUSH_DATA (push, sf->height << 16); 140 PUSH_DATA (push, rt_format); 141 BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2); 142 if (eng3d->oclass < NV40_3D_CLASS) 143 PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); 144 else 145 PUSH_DATA (push, sf->pitch); 146 PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); 147 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); 148 PUSH_DATA (push, (w << 16) | x); 149 PUSH_DATA (push, (h << 16) | y); 150 151 BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2); 152 PUSH_DATA (push, pack_rgba(ps->format, color->f)); 153 PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R | 154 NV30_3D_CLEAR_BUFFERS_COLOR_G | 155 NV30_3D_CLEAR_BUFFERS_COLOR_B | 156 NV30_3D_CLEAR_BUFFERS_COLOR_A); 157 158 nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; 159 } 160 161 static void 162 nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps, 163 unsigned buffers, double depth, unsigned stencil, 164 unsigned x, unsigned y, unsigned w, unsigned h, 165 bool render_condition_enabled) 166 { 167 struct nv30_context *nv30 = nv30_context(pipe); 168 struct nv30_surface *sf = nv30_surface(ps); 169 struct nv30_miptree *mt = nv30_miptree(ps->texture); 170 struct nouveau_pushbuf *push = nv30->base.pushbuf; 171 struct nouveau_object *eng3d = nv30->screen->eng3d; 172 struct nouveau_pushbuf_refn refn; 173 uint32_t rt_format, mode = 0; 174 175 rt_format = nv30_format(pipe->screen, ps->format)->hw; 176 if (util_format_get_blocksize(ps->format) == 4) 177 rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8; 178 else 179 rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5; 180 181 if (nv30_miptree(ps->texture)->swizzled) { 182 rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; 183 rt_format |= util_logbase2(sf->width) << 16; 184 rt_format |= util_logbase2(sf->height) << 24; 185 } else { 186 rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; 187 } 188 189 if (buffers & PIPE_CLEAR_DEPTH) 190 mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; 191 if (buffers & PIPE_CLEAR_STENCIL) 192 mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; 193 194 refn.bo = mt->base.bo; 195 refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; 196 if (nouveau_pushbuf_space(push, 32, 1, 0) || 197 nouveau_pushbuf_refn (push, &refn, 1)) 198 return; 199 200 BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); 201 PUSH_DATA (push, 0); 202 BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); 203 PUSH_DATA (push, sf->width << 16); 204 PUSH_DATA (push, sf->height << 16); 205 PUSH_DATA (push, rt_format); 206 if (eng3d->oclass < NV40_3D_CLASS) { 207 BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1); 208 PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); 209 } else { 210 BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1); 211 PUSH_DATA (push, sf->pitch); 212 } 213 BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1); 214 PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); 215 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); 216 PUSH_DATA (push, (w << 16) | x); 217 PUSH_DATA (push, (h << 16) | y); 218 219 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1); 220 PUSH_DATA (push, pack_zeta(ps->format, depth, stencil)); 221 BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1); 222 PUSH_DATA (push, mode); 223 224 nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; 225 } 226 227 void 228 nv30_clear_init(struct pipe_context *pipe) 229 { 230 pipe->clear = nv30_clear; 231 pipe->clear_render_target = nv30_clear_render_target; 232 pipe->clear_depth_stencil = nv30_clear_depth_stencil; 233 } 234