OSDN Git Service

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