2 * Copyright 2008 Ben Skeggs
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #define __NOUVEAU_PUSH_H__
25 #include "nouveau/nouveau_pushbuf.h"
26 #include "nv50_context.h"
27 #include "nv50_resource.h"
28 #include "pipe/p_defines.h"
29 #include "util/u_inlines.h"
30 #include "util/u_pack_color.h"
32 #include "util/u_format.h"
34 /* return TRUE for formats that can be converted among each other by NV50_2D */
36 nv50_2d_format_faithful(enum pipe_format format
)
39 case PIPE_FORMAT_B8G8R8A8_UNORM
:
40 case PIPE_FORMAT_B8G8R8X8_UNORM
:
41 case PIPE_FORMAT_B8G8R8A8_SRGB
:
42 case PIPE_FORMAT_B8G8R8X8_SRGB
:
43 case PIPE_FORMAT_B5G6R5_UNORM
:
44 case PIPE_FORMAT_B5G5R5A1_UNORM
:
45 case PIPE_FORMAT_B10G10R10A2_UNORM
:
46 case PIPE_FORMAT_R8_UNORM
:
47 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
48 case PIPE_FORMAT_R32G32B32_FLOAT
:
56 nv50_2d_format(enum pipe_format format
)
58 uint8_t id
= nv50_format_table
[format
].rt
;
60 /* Hardware values for color formats range from 0xc0 to 0xff,
61 * but the 2D engine doesn't support all of them.
63 if ((id
>= 0xc0) && (0xff0843e080608409ULL
& (1ULL << (id
- 0xc0))))
66 switch (util_format_get_blocksize(format
)) {
68 return NV50_2D_DST_FORMAT_R8_UNORM
;
70 return NV50_2D_DST_FORMAT_R16_UNORM
;
72 return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM
;
79 nv50_surface_set(struct nv50_screen
*screen
, struct pipe_surface
*ps
, int dst
)
81 struct nv50_miptree
*mt
= nv50_miptree(ps
->texture
);
82 struct nouveau_channel
*chan
= screen
->eng2d
->channel
;
83 struct nouveau_grobj
*eng2d
= screen
->eng2d
;
84 struct nouveau_bo
*bo
= nv50_miptree(ps
->texture
)->base
.bo
;
85 int format
, mthd
= dst
? NV50_2D_DST_FORMAT
: NV50_2D_SRC_FORMAT
;
86 int flags
= NOUVEAU_BO_VRAM
| (dst
? NOUVEAU_BO_WR
: NOUVEAU_BO_RD
);
88 format
= nv50_2d_format(ps
->format
);
90 NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
91 util_format_name(ps
->format
));
95 if (!nouveau_bo_tile_layout(bo
)) {
96 BEGIN_RING(chan
, eng2d
, mthd
, 2);
97 OUT_RING (chan
, format
);
99 BEGIN_RING(chan
, eng2d
, mthd
+ 0x14, 5);
100 OUT_RING (chan
, mt
->level
[ps
->level
].pitch
);
101 OUT_RING (chan
, ps
->width
);
102 OUT_RING (chan
, ps
->height
);
103 OUT_RELOCh(chan
, bo
, ps
->offset
, flags
);
104 OUT_RELOCl(chan
, bo
, ps
->offset
, flags
);
106 BEGIN_RING(chan
, eng2d
, mthd
, 5);
107 OUT_RING (chan
, format
);
109 OUT_RING (chan
, mt
->level
[ps
->level
].tile_mode
<< 4);
112 BEGIN_RING(chan
, eng2d
, mthd
+ 0x18, 4);
113 OUT_RING (chan
, ps
->width
);
114 OUT_RING (chan
, ps
->height
);
115 OUT_RELOCh(chan
, bo
, ps
->offset
, flags
);
116 OUT_RELOCl(chan
, bo
, ps
->offset
, flags
);
121 BEGIN_RING(chan
, eng2d
, NV50_2D_CLIP_X
, 4);
124 OUT_RING (chan
, surf
->width
);
125 OUT_RING (chan
, surf
->height
);
133 nv50_surface_do_copy(struct nv50_screen
*screen
, struct pipe_surface
*dst
,
134 int dx
, int dy
, struct pipe_surface
*src
, int sx
, int sy
,
137 struct nouveau_channel
*chan
= screen
->eng2d
->channel
;
138 struct nouveau_grobj
*eng2d
= screen
->eng2d
;
141 ret
= MARK_RING(chan
, 2*16 + 32, 4);
145 ret
= nv50_surface_set(screen
, dst
, 1);
149 ret
= nv50_surface_set(screen
, src
, 0);
153 BEGIN_RING(chan
, eng2d
, 0x088c, 1);
155 BEGIN_RING(chan
, eng2d
, NV50_2D_BLIT_DST_X
, 4);
160 BEGIN_RING(chan
, eng2d
, 0x08c0, 4);
165 BEGIN_RING(chan
, eng2d
, 0x08d0, 4);
175 nv50_surface_copy(struct pipe_context
*pipe
,
176 struct pipe_resource
*dest
, struct pipe_subresource subdst
,
177 unsigned destx
, unsigned desty
, unsigned destz
,
178 struct pipe_resource
*src
, struct pipe_subresource subsrc
,
179 unsigned srcx
, unsigned srcy
, unsigned srcz
,
180 unsigned width
, unsigned height
)
182 struct nv50_context
*nv50
= nv50_context(pipe
);
183 struct nv50_screen
*screen
= nv50
->screen
;
184 struct pipe_surface
*ps_dst
, *ps_src
;
186 assert((src
->format
== dest
->format
) ||
187 (nv50_2d_format_faithful(src
->format
) &&
188 nv50_2d_format_faithful(dest
->format
)));
190 ps_src
= nv50_miptree_surface_new(pipe
->screen
, src
, subsrc
.face
,
191 subsrc
.level
, srcz
, 0 /* bind flags */);
192 ps_dst
= nv50_miptree_surface_new(pipe
->screen
, dest
, subdst
.face
,
193 subdst
.level
, destz
, 0 /* bindflags */);
195 nv50_surface_do_copy(screen
, ps_dst
, destx
, desty
, ps_src
, srcx
,
196 srcy
, width
, height
);
198 nv50_miptree_surface_del(ps_src
);
199 nv50_miptree_surface_del(ps_dst
);
203 nv50_clear_render_target(struct pipe_context
*pipe
,
204 struct pipe_surface
*dst
,
206 unsigned dstx
, unsigned dsty
,
207 unsigned width
, unsigned height
)
209 struct nv50_context
*nv50
= nv50_context(pipe
);
210 struct nv50_screen
*screen
= nv50
->screen
;
211 struct nouveau_channel
*chan
= screen
->base
.channel
;
212 struct nouveau_grobj
*tesla
= screen
->tesla
;
213 struct nv50_miptree
*mt
= nv50_miptree(dst
->texture
);
214 struct nouveau_bo
*bo
= mt
->base
.bo
;
216 BEGIN_RING(chan
, tesla
, NV50TCL_CLEAR_COLOR(0), 4);
217 OUT_RINGf (chan
, rgba
[0]);
218 OUT_RINGf (chan
, rgba
[1]);
219 OUT_RINGf (chan
, rgba
[2]);
220 OUT_RINGf (chan
, rgba
[3]);
222 if (MARK_RING(chan
, 18, 2))
225 BEGIN_RING(chan
, tesla
, NV50TCL_RT_CONTROL
, 1);
227 BEGIN_RING(chan
, tesla
, NV50TCL_RT_ADDRESS_HIGH(0), 5);
228 OUT_RELOCh(chan
, bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
229 OUT_RELOCl(chan
, bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
230 OUT_RING (chan
, nv50_format_table
[dst
->format
].rt
);
231 OUT_RING (chan
, mt
->level
[dst
->level
].tile_mode
<< 4);
233 BEGIN_RING(chan
, tesla
, NV50TCL_RT_HORIZ(0), 2);
234 OUT_RING (chan
, dst
->width
);
235 OUT_RING (chan
, dst
->height
);
236 BEGIN_RING(chan
, tesla
, NV50TCL_RT_ARRAY_MODE
, 1);
239 /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
241 BEGIN_RING(chan
, tesla
, NV50TCL_VIEWPORT_HORIZ(0), 2);
242 OUT_RING (chan
, (width
<< 16) | dstx
);
243 OUT_RING (chan
, (height
<< 16) | dsty
);
245 BEGIN_RING(chan
, tesla
, NV50TCL_CLEAR_BUFFERS
, 1);
246 OUT_RING (chan
, 0x3c);
248 nv50
->dirty
|= NV50_NEW_FRAMEBUFFER
;
252 nv50_clear_depth_stencil(struct pipe_context
*pipe
,
253 struct pipe_surface
*dst
,
254 unsigned clear_flags
,
257 unsigned dstx
, unsigned dsty
,
258 unsigned width
, unsigned height
)
260 struct nv50_context
*nv50
= nv50_context(pipe
);
261 struct nv50_screen
*screen
= nv50
->screen
;
262 struct nouveau_channel
*chan
= screen
->base
.channel
;
263 struct nouveau_grobj
*tesla
= screen
->tesla
;
264 struct nv50_miptree
*mt
= nv50_miptree(dst
->texture
);
265 struct nouveau_bo
*bo
= mt
->base
.bo
;
268 if (clear_flags
& PIPE_CLEAR_DEPTH
) {
269 BEGIN_RING(chan
, tesla
, NV50TCL_CLEAR_DEPTH
, 1);
270 OUT_RINGf (chan
, depth
);
271 mode
|= NV50TCL_CLEAR_BUFFERS_Z
;
274 if (clear_flags
& PIPE_CLEAR_STENCIL
) {
275 BEGIN_RING(chan
, tesla
, NV50TCL_CLEAR_STENCIL
, 1);
276 OUT_RING (chan
, stencil
& 0xff);
277 mode
|= NV50TCL_CLEAR_BUFFERS_S
;
280 if (MARK_RING(chan
, 17, 2))
283 BEGIN_RING(chan
, tesla
, NV50TCL_ZETA_ADDRESS_HIGH
, 5);
284 OUT_RELOCh(chan
, bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
285 OUT_RELOCl(chan
, bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
286 OUT_RING (chan
, nv50_format_table
[dst
->format
].rt
);
287 OUT_RING (chan
, mt
->level
[dst
->level
].tile_mode
<< 4);
289 BEGIN_RING(chan
, tesla
, NV50TCL_ZETA_ENABLE
, 1);
291 BEGIN_RING(chan
, tesla
, NV50TCL_ZETA_HORIZ
, 3);
292 OUT_RING (chan
, dst
->width
);
293 OUT_RING (chan
, dst
->height
);
294 OUT_RING (chan
, (1 << 16) | 1);
296 BEGIN_RING(chan
, tesla
, NV50TCL_VIEWPORT_HORIZ(0), 2);
297 OUT_RING (chan
, (width
<< 16) | dstx
);
298 OUT_RING (chan
, (height
<< 16) | dsty
);
300 BEGIN_RING(chan
, tesla
, NV50TCL_CLEAR_BUFFERS
, 1);
301 OUT_RING (chan
, mode
);
303 nv50
->dirty
|= NV50_NEW_FRAMEBUFFER
;
307 nv50_init_surface_functions(struct nv50_context
*nv50
)
309 nv50
->pipe
.resource_copy_region
= nv50_surface_copy
;
310 nv50
->pipe
.clear_render_target
= nv50_clear_render_target
;
311 nv50
->pipe
.clear_depth_stencil
= nv50_clear_depth_stencil
;