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