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_winsys.h"
34 #include "nv30/nv30_format.h"
35
36 static inline uint32_t
pack_rgba(enum pipe_format format,const float * rgba)37 pack_rgba(enum pipe_format format, const float *rgba)
38 {
39 union util_color uc;
40 util_pack_color(rgba, format, &uc);
41 return uc.ui[0];
42 }
43
44 static inline uint32_t
pack_zeta(enum pipe_format format,double depth,unsigned stencil)45 pack_zeta(enum pipe_format format, double depth, unsigned stencil)
46 {
47 uint32_t zuint = (uint32_t)(depth * 4294967295.0);
48 if (format != PIPE_FORMAT_Z16_UNORM)
49 return (zuint & 0xffffff00) | (stencil & 0xff);
50 return zuint >> 16;
51 }
52
53 static void
nv30_clear(struct pipe_context * pipe,unsigned buffers,const struct pipe_scissor_state * scissor_state,const union pipe_color_union * color,double depth,unsigned stencil)54 nv30_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
55 const union pipe_color_union *color, double depth, unsigned stencil)
56 {
57 struct nv30_context *nv30 = nv30_context(pipe);
58 struct nouveau_pushbuf *push = nv30->base.pushbuf;
59 struct pipe_framebuffer_state *fb = &nv30->framebuffer;
60 uint32_t colr = 0, zeta = 0, mode = 0;
61
62 if (!nv30_state_validate(nv30, NV30_NEW_FRAMEBUFFER, true))
63 return;
64
65 if (scissor_state) {
66 uint32_t minx = scissor_state->minx;
67 uint32_t maxx = MIN2(fb->width, scissor_state->maxx);
68 uint32_t miny = scissor_state->miny;
69 uint32_t maxy = MIN2(fb->height, scissor_state->maxy);
70
71 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
72 PUSH_DATA (push, minx | (maxx - minx) << 16);
73 PUSH_DATA (push, miny | (maxy - miny) << 16);
74 }
75 else {
76 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
77 PUSH_DATA (push, 0x10000000);
78 PUSH_DATA (push, 0x10000000);
79 }
80
81 if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
82 colr = pack_rgba(fb->cbufs[0]->format, color->f);
83 mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R |
84 NV30_3D_CLEAR_BUFFERS_COLOR_G |
85 NV30_3D_CLEAR_BUFFERS_COLOR_B |
86 NV30_3D_CLEAR_BUFFERS_COLOR_A;
87 }
88
89 if (fb->zsbuf) {
90 zeta = pack_zeta(fb->zsbuf->format, depth, stencil);
91 if (buffers & PIPE_CLEAR_DEPTH)
92 mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
93 if (buffers & PIPE_CLEAR_STENCIL) {
94 mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
95 BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 2);
96 PUSH_DATA (push, 0);
97 PUSH_DATA (push, 0x000000ff);
98 nv30->dirty |= NV30_NEW_ZSA;
99 }
100 }
101
102 /*XXX: wtf? fixes clears sometimes not clearing on nv3x... */
103 if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) {
104 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
105 PUSH_DATA (push, zeta);
106 PUSH_DATA (push, colr);
107 PUSH_DATA (push, mode);
108 }
109
110 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
111 PUSH_DATA (push, zeta);
112 PUSH_DATA (push, colr);
113 PUSH_DATA (push, mode);
114
115 nv30_state_release(nv30);
116
117 /* Make sure regular draw commands will get their scissor state set */
118 nv30->dirty |= NV30_NEW_SCISSOR;
119 nv30->state.scissor_off = 0;
120 }
121
122 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,bool render_condition_enabled)123 nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps,
124 const union pipe_color_union *color,
125 unsigned x, unsigned y, unsigned w, unsigned h,
126 bool render_condition_enabled)
127 {
128 struct nv30_context *nv30 = nv30_context(pipe);
129 struct nv30_surface *sf = nv30_surface(ps);
130 struct nv30_miptree *mt = nv30_miptree(ps->texture);
131 struct nouveau_pushbuf *push = nv30->base.pushbuf;
132 struct nouveau_object *eng3d = nv30->screen->eng3d;
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 if (!PUSH_SPACE_EX(push, 32, 1, 0) ||
150 PUSH_REF1(push, mt->base.bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
151 return;
152
153 BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
154 PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);
155 BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
156 PUSH_DATA (push, sf->width << 16);
157 PUSH_DATA (push, sf->height << 16);
158 PUSH_DATA (push, rt_format);
159 BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2);
160 if (eng3d->oclass < NV40_3D_CLASS)
161 PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
162 else
163 PUSH_DATA (push, sf->pitch);
164 PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
165 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
166 PUSH_DATA (push, (w << 16) | x);
167 PUSH_DATA (push, (h << 16) | y);
168
169 BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2);
170 PUSH_DATA (push, pack_rgba(ps->format, color->f));
171 PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R |
172 NV30_3D_CLEAR_BUFFERS_COLOR_G |
173 NV30_3D_CLEAR_BUFFERS_COLOR_B |
174 NV30_3D_CLEAR_BUFFERS_COLOR_A);
175
176 nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
177 nv30->state.scissor_off = 0;
178 }
179
180 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,bool render_condition_enabled)181 nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps,
182 unsigned buffers, double depth, unsigned stencil,
183 unsigned x, unsigned y, unsigned w, unsigned h,
184 bool render_condition_enabled)
185 {
186 struct nv30_context *nv30 = nv30_context(pipe);
187 struct nv30_surface *sf = nv30_surface(ps);
188 struct nv30_miptree *mt = nv30_miptree(ps->texture);
189 struct nouveau_pushbuf *push = nv30->base.pushbuf;
190 struct nouveau_object *eng3d = nv30->screen->eng3d;
191 uint32_t rt_format, mode = 0;
192
193 rt_format = nv30_format(pipe->screen, ps->format)->hw;
194 if (util_format_get_blocksize(ps->format) == 4)
195 rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
196 else
197 rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
198
199 if (nv30_miptree(ps->texture)->swizzled) {
200 rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
201 rt_format |= util_logbase2(sf->width) << 16;
202 rt_format |= util_logbase2(sf->height) << 24;
203 } else {
204 rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
205 }
206
207 if (buffers & PIPE_CLEAR_DEPTH)
208 mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
209 if (buffers & PIPE_CLEAR_STENCIL)
210 mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
211
212 if (!PUSH_SPACE_EX(push, 32, 1, 0) ||
213 PUSH_REF1(push, mt->base.bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
214 return;
215
216 BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
217 PUSH_DATA (push, 0);
218 BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
219 PUSH_DATA (push, sf->width << 16);
220 PUSH_DATA (push, sf->height << 16);
221 PUSH_DATA (push, rt_format);
222 if (eng3d->oclass < NV40_3D_CLASS) {
223 BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1);
224 PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
225 } else {
226 BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
227 PUSH_DATA (push, sf->pitch);
228 }
229 BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1);
230 PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
231 BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
232 PUSH_DATA (push, (w << 16) | x);
233 PUSH_DATA (push, (h << 16) | y);
234
235 BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1);
236 PUSH_DATA (push, pack_zeta(ps->format, depth, stencil));
237 BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1);
238 PUSH_DATA (push, mode);
239
240 nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
241 nv30->state.scissor_off = 0;
242 }
243
244 void
nv30_clear_init(struct pipe_context * pipe)245 nv30_clear_init(struct pipe_context *pipe)
246 {
247 pipe->clear = nv30_clear;
248 pipe->clear_render_target = nv30_clear_render_target;
249 pipe->clear_depth_stencil = nv30_clear_depth_stencil;
250 }
251