Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2007 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 "util/u_rect.h"
29
#include "util/u_surface.h"
30
#include "lp_context.h"
31
#include "lp_flush.h"
32
#include "lp_limits.h"
33
#include "lp_surface.h"
34
#include "lp_texture.h"
35
#include "lp_query.h"
36
 
37
 
38
/**
39
 * Adjust x, y, width, height to lie on tile bounds.
40
 */
41
static void
42
adjust_to_tile_bounds(unsigned x, unsigned y, unsigned width, unsigned height,
43
                      unsigned *x_tile, unsigned *y_tile,
44
                      unsigned *w_tile, unsigned *h_tile)
45
{
46
   *x_tile = x & ~(TILE_SIZE - 1);
47
   *y_tile = y & ~(TILE_SIZE - 1);
48
   *w_tile = ((x + width + TILE_SIZE - 1) & ~(TILE_SIZE - 1)) - *x_tile;
49
   *h_tile = ((y + height + TILE_SIZE - 1) & ~(TILE_SIZE - 1)) - *y_tile;
50
}
51
 
52
 
53
 
54
static void
55
lp_resource_copy(struct pipe_context *pipe,
56
                 struct pipe_resource *dst, unsigned dst_level,
57
                 unsigned dstx, unsigned dsty, unsigned dstz,
58
                 struct pipe_resource *src, unsigned src_level,
59
                 const struct pipe_box *src_box)
60
{
61
   struct llvmpipe_resource *src_tex = llvmpipe_resource(src);
62
   struct llvmpipe_resource *dst_tex = llvmpipe_resource(dst);
63
   const enum pipe_format format = src_tex->base.format;
64
   unsigned width = src_box->width;
65
   unsigned height = src_box->height;
66
   unsigned depth = src_box->depth;
67
   unsigned z;
68
 
69
   llvmpipe_flush_resource(pipe,
70
                           dst, dst_level,
71
                           FALSE, /* read_only */
72
                           TRUE, /* cpu_access */
73
                           FALSE, /* do_not_block */
74
                           "blit dest");
75
 
76
   llvmpipe_flush_resource(pipe,
77
                           src, src_level,
78
                           TRUE, /* read_only */
79
                           TRUE, /* cpu_access */
80
                           FALSE, /* do_not_block */
81
                           "blit src");
82
 
83
   /* Fallback for buffers. */
84
   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
85
      util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
86
                                src, src_level, src_box);
87
      return;
88
   }
89
 
90
   /*
91
   printf("surface copy from %u lvl %u to %u lvl %u: %u,%u,%u to %u,%u,%u %u x %u x %u\n",
92
          src_tex->id, src_level, dst_tex->id, dst_level,
93
          src_box->x, src_box->y, src_box->z, dstx, dsty, dstz,
94
          src_box->width, src_box->height, src_box->depth);
95
   */
96
 
97
   for (z = 0; z < src_box->depth; z++){
98
 
99
      /* set src tiles to linear layout */
100
      {
101
         unsigned tx, ty, tw, th;
102
         unsigned x, y;
103
 
104
         adjust_to_tile_bounds(src_box->x, src_box->y, width, height,
105
                               &tx, &ty, &tw, &th);
106
 
107
         for (y = 0; y < th; y += TILE_SIZE) {
108
            for (x = 0; x < tw; x += TILE_SIZE) {
109
               (void) llvmpipe_get_texture_tile_linear(src_tex,
110
                                                       src_box->z + z, src_level,
111
                                                       LP_TEX_USAGE_READ,
112
                                                       tx + x, ty + y);
113
            }
114
         }
115
      }
116
 
117
      /* set dst tiles to linear layout */
118
      {
119
         unsigned tx, ty, tw, th;
120
         unsigned x, y;
121
         enum lp_texture_usage usage;
122
 
123
         adjust_to_tile_bounds(dstx, dsty, width, height, &tx, &ty, &tw, &th);
124
 
125
         for (y = 0; y < th; y += TILE_SIZE) {
126
            boolean contained_y = ty + y >= dsty &&
127
                                  ty + y + TILE_SIZE <= dsty + height ?
128
                                  TRUE : FALSE;
129
 
130
            for (x = 0; x < tw; x += TILE_SIZE) {
131
               boolean contained_x = tx + x >= dstx &&
132
                                     tx + x + TILE_SIZE <= dstx + width ?
133
                                     TRUE : FALSE;
134
 
135
               /*
136
                * Set the usage mode to WRITE_ALL for the tiles which are
137
                * completely contained by the dest rectangle.
138
                */
139
               if (contained_y && contained_x)
140
                  usage = LP_TEX_USAGE_WRITE_ALL;
141
               else
142
                  usage = LP_TEX_USAGE_READ_WRITE;
143
 
144
               (void) llvmpipe_get_texture_tile_linear(dst_tex,
145
                                                       dstz + z, dst_level,
146
                                                       usage,
147
                                                       tx + x, ty + y);
148
            }
149
         }
150
      }
151
   }
152
 
153
   /* copy */
154
   {
155
      const ubyte *src_linear_ptr
156
         = llvmpipe_get_texture_image_address(src_tex, src_box->z,
157
                                              src_level);
158
      ubyte *dst_linear_ptr
159
         = llvmpipe_get_texture_image_address(dst_tex, dstz,
160
                                              dst_level);
161
 
162
      if (dst_linear_ptr && src_linear_ptr) {
163
         util_copy_box(dst_linear_ptr, format,
164
                       llvmpipe_resource_stride(&dst_tex->base, dst_level),
165
                       dst_tex->img_stride[dst_level],
166
                       dstx, dsty, 0,
167
                       width, height, depth,
168
                       src_linear_ptr,
169
                       llvmpipe_resource_stride(&src_tex->base, src_level),
170
                       src_tex->img_stride[src_level],
171
                       src_box->x, src_box->y, 0);
172
      }
173
   }
174
}
175
 
176
 
177
static void lp_blit(struct pipe_context *pipe,
178
                    const struct pipe_blit_info *blit_info)
179
{
180
   struct llvmpipe_context *lp = llvmpipe_context(pipe);
181
   struct pipe_blit_info info = *blit_info;
182
 
183
   if (info.src.resource->nr_samples > 1 &&
184
       info.dst.resource->nr_samples <= 1 &&
185
       !util_format_is_depth_or_stencil(info.src.resource->format) &&
186
       !util_format_is_pure_integer(info.src.resource->format)) {
187
      debug_printf("llvmpipe: color resolve unimplemented\n");
188
      return;
189
   }
190
 
191
   if (util_try_blit_via_copy_region(pipe, &info)) {
192
      return; /* done */
193
   }
194
 
195
   if (info.mask & PIPE_MASK_S) {
196
      debug_printf("llvmpipe: cannot blit stencil, skipping\n");
197
      info.mask &= ~PIPE_MASK_S;
198
   }
199
 
200
   if (!util_blitter_is_blit_supported(lp->blitter, &info)) {
201
      debug_printf("llvmpipe: blit unsupported %s -> %s\n",
202
                   util_format_short_name(info.src.resource->format),
203
                   util_format_short_name(info.dst.resource->format));
204
      return;
205
   }
206
 
207
   /* XXX turn off occlusion and streamout queries */
208
 
209
   util_blitter_save_vertex_buffer_slot(lp->blitter, lp->vertex_buffer);
210
   util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems);
211
   util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs);
212
   util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs);
213
   util_blitter_save_so_targets(lp->blitter, lp->num_so_targets,
214
                                (struct pipe_stream_output_target**)lp->so_targets);
215
   util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer);
216
   util_blitter_save_viewport(lp->blitter, &lp->viewports[0]);
217
   util_blitter_save_scissor(lp->blitter, &lp->scissors[0]);
218
   util_blitter_save_fragment_shader(lp->blitter, lp->fs);
219
   util_blitter_save_blend(lp->blitter, (void*)lp->blend);
220
   util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil);
221
   util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref);
222
   /*util_blitter_save_sample_mask(sp->blitter, lp->sample_mask);*/
223
   util_blitter_save_framebuffer(lp->blitter, &lp->framebuffer);
224
   util_blitter_save_fragment_sampler_states(lp->blitter,
225
                     lp->num_samplers[PIPE_SHADER_FRAGMENT],
226
                     (void**)lp->samplers[PIPE_SHADER_FRAGMENT]);
227
   util_blitter_save_fragment_sampler_views(lp->blitter,
228
                     lp->num_sampler_views[PIPE_SHADER_FRAGMENT],
229
                     lp->sampler_views[PIPE_SHADER_FRAGMENT]);
230
   util_blitter_save_render_condition(lp->blitter, lp->render_cond_query,
231
                                      lp->render_cond_cond, lp->render_cond_mode);
232
   util_blitter_blit(lp->blitter, &info);
233
}
234
 
235
 
236
static struct pipe_surface *
237
llvmpipe_create_surface(struct pipe_context *pipe,
238
                        struct pipe_resource *pt,
239
                        const struct pipe_surface *surf_tmpl)
240
{
241
   struct pipe_surface *ps;
242
 
243
   if (!(pt->bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET)))
244
      debug_printf("Illegal surface creation without bind flag\n");
245
 
246
   ps = CALLOC_STRUCT(pipe_surface);
247
   if (ps) {
248
      pipe_reference_init(&ps->reference, 1);
249
      pipe_resource_reference(&ps->texture, pt);
250
      ps->context = pipe;
251
      ps->format = surf_tmpl->format;
252
      if (llvmpipe_resource_is_texture(pt)) {
253
         assert(surf_tmpl->u.tex.level <= pt->last_level);
254
         assert(surf_tmpl->u.tex.first_layer <= surf_tmpl->u.tex.last_layer);
255
         ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
256
         ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
257
         ps->u.tex.level = surf_tmpl->u.tex.level;
258
         ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
259
         ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
260
      }
261
      else {
262
         /* setting width as number of elements should get us correct renderbuffer width */
263
         ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1;
264
         ps->height = pt->height0;
265
         ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
266
         ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
267
         assert(ps->u.buf.first_element <= ps->u.buf.last_element);
268
         assert(util_format_get_blocksize(surf_tmpl->format) *
269
                (ps->u.buf.last_element + 1) <= pt->width0);
270
      }
271
   }
272
   return ps;
273
}
274
 
275
 
276
static void
277
llvmpipe_surface_destroy(struct pipe_context *pipe,
278
                         struct pipe_surface *surf)
279
{
280
   /* Effectively do the texture_update work here - if texture images
281
    * needed post-processing to put them into hardware layout, this is
282
    * where it would happen.  For llvmpipe, nothing to do.
283
    */
284
   assert(surf->texture);
285
   pipe_resource_reference(&surf->texture, NULL);
286
   FREE(surf);
287
}
288
 
289
 
290
static void
291
llvmpipe_clear_render_target(struct pipe_context *pipe,
292
                             struct pipe_surface *dst,
293
                             const union pipe_color_union *color,
294
                             unsigned dstx, unsigned dsty,
295
                             unsigned width, unsigned height)
296
{
297
   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
298
 
299
   if (!llvmpipe_check_render_cond(llvmpipe))
300
      return;
301
 
302
   util_clear_render_target(pipe, dst, color,
303
                            dstx, dsty, width, height);
304
}
305
 
306
 
307
static void
308
llvmpipe_clear_depth_stencil(struct pipe_context *pipe,
309
                             struct pipe_surface *dst,
310
                             unsigned clear_flags,
311
                             double depth,
312
                             unsigned stencil,
313
                             unsigned dstx, unsigned dsty,
314
                             unsigned width, unsigned height)
315
{
316
   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
317
 
318
   if (!llvmpipe_check_render_cond(llvmpipe))
319
      return;
320
 
321
   util_clear_depth_stencil(pipe, dst, clear_flags,
322
                            depth, stencil,
323
                            dstx, dsty, width, height);
324
}
325
 
326
 
327
void
328
llvmpipe_init_surface_functions(struct llvmpipe_context *lp)
329
{
330
   lp->pipe.clear_render_target = llvmpipe_clear_render_target;
331
   lp->pipe.clear_depth_stencil = llvmpipe_clear_depth_stencil;
332
   lp->pipe.create_surface = llvmpipe_create_surface;
333
   lp->pipe.surface_destroy = llvmpipe_surface_destroy;
334
   /* These two are not actually functions dealing with surfaces */
335
   lp->pipe.resource_copy_region = lp_resource_copy;
336
   lp->pipe.blit = lp_blit;
337
}