• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #include "i915_surface.h"
29 #include "i915_resource.h"
30 #include "i915_state.h"
31 #include "i915_blit.h"
32 #include "i915_reg.h"
33 #include "i915_screen.h"
34 #include "pipe/p_defines.h"
35 #include "util/u_inlines.h"
36 #include "util/u_math.h"
37 #include "util/u_format.h"
38 #include "util/u_memory.h"
39 #include "util/u_pack_color.h"
40 #include "util/u_surface.h"
41 
42 /*
43  * surface functions using the render engine
44  */
45 
46 static void
i915_surface_copy_render(struct pipe_context * pipe,struct pipe_resource * dst,unsigned dst_level,unsigned dstx,unsigned dsty,unsigned dstz,struct pipe_resource * src,unsigned src_level,const struct pipe_box * src_box)47 i915_surface_copy_render(struct pipe_context *pipe,
48                          struct pipe_resource *dst, unsigned dst_level,
49                          unsigned dstx, unsigned dsty, unsigned dstz,
50                          struct pipe_resource *src, unsigned src_level,
51                          const struct pipe_box *src_box)
52 {
53    struct i915_context *i915 = i915_context(pipe);
54 
55    /* Fallback for buffers. */
56    if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
57       util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
58                                 src, src_level, src_box);
59       return;
60    }
61 
62    if (!util_blitter_is_copy_supported(i915->blitter, dst, src,
63                                        PIPE_MASK_RGBAZS)) {
64       util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
65                                 src, src_level, src_box);
66       return;
67    }
68 
69    util_blitter_save_blend(i915->blitter, (void *)i915->blend);
70    util_blitter_save_depth_stencil_alpha(i915->blitter, (void *)i915->depth_stencil);
71    util_blitter_save_stencil_ref(i915->blitter, &i915->stencil_ref);
72    util_blitter_save_rasterizer(i915->blitter, (void *)i915->rasterizer);
73    util_blitter_save_fragment_shader(i915->blitter, i915->saved_fs);
74    util_blitter_save_vertex_shader(i915->blitter, i915->saved_vs);
75    util_blitter_save_viewport(i915->blitter, &i915->viewport);
76    util_blitter_save_vertex_elements(i915->blitter, i915->saved_velems);
77    util_blitter_save_vertex_buffers(i915->blitter, i915->saved_nr_vertex_buffers,
78                                     i915->saved_vertex_buffers);
79 
80    util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
81 
82    util_blitter_save_fragment_sampler_states(i915->blitter,
83                                              i915->saved_nr_samplers,
84                                              i915->saved_samplers);
85    util_blitter_save_fragment_sampler_views(i915->blitter,
86                                             i915->saved_nr_sampler_views,
87                                             i915->saved_sampler_views);
88 
89    util_blitter_copy_texture(i915->blitter, dst, dst_level, ~0, dstx, dsty, dstz,
90                             src, src_level, 0, src_box);
91 }
92 
93 static void
i915_clear_render_target_render(struct pipe_context * pipe,struct pipe_surface * dst,const union pipe_color_union * color,unsigned dstx,unsigned dsty,unsigned width,unsigned height)94 i915_clear_render_target_render(struct pipe_context *pipe,
95                                 struct pipe_surface *dst,
96                                 const union pipe_color_union *color,
97                                 unsigned dstx, unsigned dsty,
98                                 unsigned width, unsigned height)
99 {
100    struct i915_context *i915 = i915_context(pipe);
101    struct pipe_framebuffer_state fb_state;
102 
103    util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
104 
105    fb_state.width = dst->width;
106    fb_state.height = dst->height;
107    fb_state.nr_cbufs = 1;
108    fb_state.cbufs[0] = dst;
109    fb_state.zsbuf = NULL;
110    pipe->set_framebuffer_state(pipe, &fb_state);
111 
112    if (i915->dirty)
113       i915_update_derived(i915);
114 
115    i915_clear_emit(pipe, PIPE_CLEAR_COLOR, color, 0.0, 0x0,
116                    dstx, dsty, width, height);
117 
118    pipe->set_framebuffer_state(pipe, &i915->blitter->saved_fb_state);
119    util_unreference_framebuffer_state(&i915->blitter->saved_fb_state);
120    i915->blitter->saved_fb_state.nr_cbufs = ~0;
121 }
122 
123 static void
i915_clear_depth_stencil_render(struct pipe_context * pipe,struct pipe_surface * dst,unsigned clear_flags,double depth,unsigned stencil,unsigned dstx,unsigned dsty,unsigned width,unsigned height)124 i915_clear_depth_stencil_render(struct pipe_context *pipe,
125                                 struct pipe_surface *dst,
126                                 unsigned clear_flags,
127                                 double depth,
128                                 unsigned stencil,
129                                 unsigned dstx, unsigned dsty,
130                                 unsigned width, unsigned height)
131 {
132    struct i915_context *i915 = i915_context(pipe);
133    struct pipe_framebuffer_state fb_state;
134 
135    util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
136 
137    fb_state.width = dst->width;
138    fb_state.height = dst->height;
139    fb_state.nr_cbufs = 0;
140    fb_state.zsbuf = dst;
141    pipe->set_framebuffer_state(pipe, &fb_state);
142 
143    if (i915->dirty)
144       i915_update_derived(i915);
145 
146    i915_clear_emit(pipe, clear_flags & PIPE_CLEAR_DEPTHSTENCIL,
147                    NULL, depth, stencil,
148                    dstx, dsty, width, height);
149 
150    pipe->set_framebuffer_state(pipe, &i915->blitter->saved_fb_state);
151    util_unreference_framebuffer_state(&i915->blitter->saved_fb_state);
152    i915->blitter->saved_fb_state.nr_cbufs = ~0;
153 }
154 
155 /*
156  * surface functions using the blitter
157  */
158 
159 /* Assumes all values are within bounds -- no checking at this level -
160  * do it higher up if required.
161  */
162 static void
i915_surface_copy_blitter(struct pipe_context * pipe,struct pipe_resource * dst,unsigned dst_level,unsigned dstx,unsigned dsty,unsigned dstz,struct pipe_resource * src,unsigned src_level,const struct pipe_box * src_box)163 i915_surface_copy_blitter(struct pipe_context *pipe,
164                           struct pipe_resource *dst, unsigned dst_level,
165                           unsigned dstx, unsigned dsty, unsigned dstz,
166                           struct pipe_resource *src, unsigned src_level,
167                           const struct pipe_box *src_box)
168 {
169    struct i915_texture *dst_tex = i915_texture(dst);
170    struct i915_texture *src_tex = i915_texture(src);
171    struct pipe_resource *dpt = &dst_tex->b.b;
172    struct pipe_resource *spt = &src_tex->b.b;
173    unsigned dst_offset, src_offset;  /* in bytes */
174 
175    /* Fallback for buffers. */
176    if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
177       util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
178                                 src, src_level, src_box);
179       return;
180    }
181 
182    /* XXX cannot copy 3d regions at this time */
183    assert(src_box->depth == 1);
184    if (dst->target != PIPE_TEXTURE_CUBE &&
185        dst->target != PIPE_TEXTURE_3D)
186       assert(dstz == 0);
187    dst_offset = i915_texture_offset(dst_tex, dst_level, dstz);
188 
189    if (src->target != PIPE_TEXTURE_CUBE &&
190        src->target != PIPE_TEXTURE_3D)
191       assert(src_box->z == 0);
192    src_offset = i915_texture_offset(src_tex, src_level, src_box->z);
193 
194    assert( util_format_get_blocksize(dpt->format) == util_format_get_blocksize(spt->format) );
195    assert( util_format_get_blockwidth(dpt->format) == util_format_get_blockwidth(spt->format) );
196    assert( util_format_get_blockheight(dpt->format) == util_format_get_blockheight(spt->format) );
197    assert( util_format_get_blockwidth(dpt->format) == 1 );
198    assert( util_format_get_blockheight(dpt->format) == 1 );
199 
200    i915_copy_blit( i915_context(pipe),
201                    util_format_get_blocksize(dpt->format),
202                    (unsigned short) src_tex->stride, src_tex->buffer, src_offset,
203                    (unsigned short) dst_tex->stride, dst_tex->buffer, dst_offset,
204                    (short) src_box->x, (short) src_box->y, (short) dstx, (short) dsty,
205                    (short) src_box->width, (short) src_box->height );
206 }
207 
208 static void
i915_clear_render_target_blitter(struct pipe_context * pipe,struct pipe_surface * dst,const union pipe_color_union * color,unsigned dstx,unsigned dsty,unsigned width,unsigned height)209 i915_clear_render_target_blitter(struct pipe_context *pipe,
210                                  struct pipe_surface *dst,
211                                  const union pipe_color_union *color,
212                                  unsigned dstx, unsigned dsty,
213                                  unsigned width, unsigned height)
214 {
215    struct i915_texture *tex = i915_texture(dst->texture);
216    struct pipe_resource *pt = &tex->b.b;
217    union util_color uc;
218    unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);
219 
220    assert(util_format_get_blockwidth(pt->format) == 1);
221    assert(util_format_get_blockheight(pt->format) == 1);
222 
223    util_pack_color(color->f, dst->format, &uc);
224    i915_fill_blit( i915_context(pipe),
225                    util_format_get_blocksize(pt->format),
226                    XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB,
227                    (unsigned short) tex->stride,
228                    tex->buffer, offset,
229                    (short) dstx, (short) dsty,
230                    (short) width, (short) height,
231                    uc.ui );
232 }
233 
234 static void
i915_clear_depth_stencil_blitter(struct pipe_context * pipe,struct pipe_surface * dst,unsigned clear_flags,double depth,unsigned stencil,unsigned dstx,unsigned dsty,unsigned width,unsigned height)235 i915_clear_depth_stencil_blitter(struct pipe_context *pipe,
236                                  struct pipe_surface *dst,
237                                  unsigned clear_flags,
238                                  double depth,
239                                  unsigned stencil,
240                                  unsigned dstx, unsigned dsty,
241                                  unsigned width, unsigned height)
242 {
243    struct i915_texture *tex = i915_texture(dst->texture);
244    struct pipe_resource *pt = &tex->b.b;
245    unsigned packedds;
246    unsigned mask = 0;
247    unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);
248 
249    assert(util_format_get_blockwidth(pt->format) == 1);
250    assert(util_format_get_blockheight(pt->format) == 1);
251 
252    packedds = util_pack_z_stencil(dst->format, depth, stencil);
253 
254    if (clear_flags & PIPE_CLEAR_DEPTH)
255       mask |= XY_COLOR_BLT_WRITE_RGB;
256    /* XXX presumably this does read-modify-write
257       (otherwise this won't work anyway). Hence will only want to
258       do it if really have stencil and it isn't cleared */
259    if ((clear_flags & PIPE_CLEAR_STENCIL) ||
260        (dst->format != PIPE_FORMAT_Z24_UNORM_S8_UINT))
261       mask |= XY_COLOR_BLT_WRITE_ALPHA;
262 
263    i915_fill_blit( i915_context(pipe),
264                    util_format_get_blocksize(pt->format),
265                    mask,
266                    (unsigned short) tex->stride,
267                    tex->buffer, offset,
268                    (short) dstx, (short) dsty,
269                    (short) width, (short) height,
270                    packedds );
271 }
272 
273 /*
274  * Screen surface functions
275  */
276 
277 
278 static struct pipe_surface *
i915_create_surface(struct pipe_context * ctx,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl)279 i915_create_surface(struct pipe_context *ctx,
280                     struct pipe_resource *pt,
281                     const struct pipe_surface *surf_tmpl)
282 {
283    struct pipe_surface *ps;
284 
285    assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
286    if (pt->target != PIPE_TEXTURE_CUBE &&
287        pt->target != PIPE_TEXTURE_3D)
288       assert(surf_tmpl->u.tex.first_layer == 0);
289 
290    ps = CALLOC_STRUCT(pipe_surface);
291    if (ps) {
292       /* could subclass pipe_surface and store offset as it used to do */
293       pipe_reference_init(&ps->reference, 1);
294       pipe_resource_reference(&ps->texture, pt);
295       ps->format = surf_tmpl->format;
296       ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
297       ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
298       ps->u.tex.level = surf_tmpl->u.tex.level;
299       ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
300       ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
301       ps->usage = surf_tmpl->usage;
302       ps->context = ctx;
303    }
304    return ps;
305 }
306 
307 static void
i915_surface_destroy(struct pipe_context * ctx,struct pipe_surface * surf)308 i915_surface_destroy(struct pipe_context *ctx,
309                      struct pipe_surface *surf)
310 {
311    pipe_resource_reference(&surf->texture, NULL);
312    FREE(surf);
313 }
314 
315 
316 void
i915_init_surface_functions(struct i915_context * i915)317 i915_init_surface_functions(struct i915_context *i915)
318 {
319    if (i915_screen(i915->base.screen)->debug.use_blitter) {
320       i915->base.resource_copy_region = i915_surface_copy_blitter;
321       i915->base.clear_render_target = i915_clear_render_target_blitter;
322       i915->base.clear_depth_stencil = i915_clear_depth_stencil_blitter;
323    } else {
324       i915->base.resource_copy_region = i915_surface_copy_render;
325       i915->base.clear_render_target = i915_clear_render_target_render;
326       i915->base.clear_depth_stencil = i915_clear_depth_stencil_render;
327    }
328    i915->base.create_surface = i915_create_surface;
329    i915->base.surface_destroy = i915_surface_destroy;
330 }
331