• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
pack_rgba(enum pipe_format format,const float * rgba)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
pack_zeta(enum pipe_format format,double depth,unsigned stencil)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
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)53 nv30_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 
121 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)122 nv30_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 
182 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)183 nv30_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 
249 void
nv30_clear_init(struct pipe_context * pipe)250 nv30_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