Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
5564 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2003 VMware, Inc.
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 VMWARE 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
static struct pipe_surface *
43
i915_create_surface_custom(struct pipe_context *ctx,
44
                           struct pipe_resource *pt,
45
                           const struct pipe_surface *surf_tmpl,
46
                           unsigned width0,
47
                           unsigned height0);
48
/*
49
 * surface functions using the render engine
50
 */
51
 
52
static void
53
i915_util_blitter_save_states(struct i915_context *i915)
54
{
55
   util_blitter_save_blend(i915->blitter, (void *)i915->blend);
56
   util_blitter_save_depth_stencil_alpha(i915->blitter, (void *)i915->depth_stencil);
57
   util_blitter_save_stencil_ref(i915->blitter, &i915->stencil_ref);
58
   util_blitter_save_rasterizer(i915->blitter, (void *)i915->rasterizer);
59
   util_blitter_save_fragment_shader(i915->blitter, i915->fs);
60
   util_blitter_save_vertex_shader(i915->blitter, i915->vs);
61
   util_blitter_save_viewport(i915->blitter, &i915->viewport);
62
   util_blitter_save_scissor(i915->blitter, &i915->scissor);
63
   util_blitter_save_vertex_elements(i915->blitter, i915->velems);
64
   util_blitter_save_vertex_buffer_slot(i915->blitter,
65
                                    i915->vertex_buffers);
66
 
67
   util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
68
 
69
   util_blitter_save_fragment_sampler_states(i915->blitter,
70
                                             i915->num_samplers,
71
                                             (void**)i915->fragment_sampler);
72
   util_blitter_save_fragment_sampler_views(i915->blitter,
73
                                            i915->num_fragment_sampler_views,
74
                                            i915->fragment_sampler_views);
75
}
76
 
77
static void
78
i915_surface_copy_render(struct pipe_context *pipe,
79
                         struct pipe_resource *dst, unsigned dst_level,
80
                         unsigned dstx, unsigned dsty, unsigned dstz,
81
                         struct pipe_resource *src, unsigned src_level,
82
                         const struct pipe_box *src_box)
83
{
84
   struct i915_context *i915 = i915_context(pipe);
85
   unsigned src_width0 = src->width0;
86
   unsigned src_height0 = src->height0;
87
   unsigned dst_width0 = dst->width0;
88
   unsigned dst_height0 = dst->height0;
89
   struct pipe_box dstbox;
90
   struct pipe_sampler_view src_templ, *src_view;
91
   struct pipe_surface dst_templ, *dst_view;
92
   const struct util_format_description *desc;
93
 
94
   /* Fallback for buffers. */
95
   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER)
96
      goto fallback;
97
 
98
   /* Fallback for depth&stencil. XXX: see if we can use a proxy format */
99
   desc = util_format_description(src->format);
100
   if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
101
      goto fallback;
102
 
103
   desc = util_format_description(dst->format);
104
   if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
105
      goto fallback;
106
 
107
   util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
108
   util_blitter_default_src_texture(&src_templ, src, src_level);
109
 
110
   if (!util_blitter_is_copy_supported(i915->blitter, dst, src))
111
      goto fallback;
112
 
113
   i915_util_blitter_save_states(i915);
114
 
115
   dst_view = i915_create_surface_custom(pipe, dst, &dst_templ, dst_width0, dst_height0);
116
   src_view = i915_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0);
117
 
118
   u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height),
119
            abs(src_box->depth), &dstbox);
120
 
121
   util_blitter_blit_generic(i915->blitter, dst_view, &dstbox,
122
                             src_view, src_box, src_width0, src_height0,
123
                             PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL);
124
   return;
125
 
126
fallback:
127
   util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
128
                             src, src_level, src_box);
129
}
130
 
131
static void
132
i915_clear_render_target_render(struct pipe_context *pipe,
133
                                struct pipe_surface *dst,
134
                                const union pipe_color_union *color,
135
                                unsigned dstx, unsigned dsty,
136
                                unsigned width, unsigned height)
137
{
138
   struct i915_context *i915 = i915_context(pipe);
139
   struct pipe_framebuffer_state fb_state;
140
 
141
   util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
142
 
143
   fb_state.width = dst->width;
144
   fb_state.height = dst->height;
145
   fb_state.nr_cbufs = 1;
146
   fb_state.cbufs[0] = dst;
147
   fb_state.zsbuf = NULL;
148
   pipe->set_framebuffer_state(pipe, &fb_state);
149
 
150
   if (i915->dirty)
151
      i915_update_derived(i915);
152
 
153
   i915_clear_emit(pipe, PIPE_CLEAR_COLOR, color, 0.0, 0x0,
154
                   dstx, dsty, width, height);
155
 
156
   pipe->set_framebuffer_state(pipe, &i915->blitter->saved_fb_state);
157
   util_unreference_framebuffer_state(&i915->blitter->saved_fb_state);
158
   i915->blitter->saved_fb_state.nr_cbufs = ~0;
159
}
160
 
161
static void
162
i915_clear_depth_stencil_render(struct pipe_context *pipe,
163
                                struct pipe_surface *dst,
164
                                unsigned clear_flags,
165
                                double depth,
166
                                unsigned stencil,
167
                                unsigned dstx, unsigned dsty,
168
                                unsigned width, unsigned height)
169
{
170
   struct i915_context *i915 = i915_context(pipe);
171
   struct pipe_framebuffer_state fb_state;
172
 
173
   util_blitter_save_framebuffer(i915->blitter, &i915->framebuffer);
174
 
175
   fb_state.width = dst->width;
176
   fb_state.height = dst->height;
177
   fb_state.nr_cbufs = 0;
178
   fb_state.zsbuf = dst;
179
   pipe->set_framebuffer_state(pipe, &fb_state);
180
 
181
   if (i915->dirty)
182
      i915_update_derived(i915);
183
 
184
   i915_clear_emit(pipe, clear_flags & PIPE_CLEAR_DEPTHSTENCIL,
185
                   NULL, depth, stencil,
186
                   dstx, dsty, width, height);
187
 
188
   pipe->set_framebuffer_state(pipe, &i915->blitter->saved_fb_state);
189
   util_unreference_framebuffer_state(&i915->blitter->saved_fb_state);
190
   i915->blitter->saved_fb_state.nr_cbufs = ~0;
191
}
192
 
193
/*
194
 * surface functions using the blitter
195
 */
196
 
197
/* Assumes all values are within bounds -- no checking at this level -
198
 * do it higher up if required.
199
 */
200
static void
201
i915_surface_copy_blitter(struct pipe_context *pipe,
202
                          struct pipe_resource *dst, unsigned dst_level,
203
                          unsigned dstx, unsigned dsty, unsigned dstz,
204
                          struct pipe_resource *src, unsigned src_level,
205
                          const struct pipe_box *src_box)
206
{
207
   struct i915_texture *dst_tex = i915_texture(dst);
208
   struct i915_texture *src_tex = i915_texture(src);
209
   struct pipe_resource *dpt = &dst_tex->b.b;
210
   struct pipe_resource *spt = &src_tex->b.b;
211
   unsigned dst_offset, src_offset;  /* in bytes */
212
 
213
   /* Fallback for buffers. */
214
   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
215
      util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
216
                                src, src_level, src_box);
217
      return;
218
   }
219
 
220
   /* XXX cannot copy 3d regions at this time */
221
   assert(src_box->depth == 1);
222
   if (dst->target != PIPE_TEXTURE_CUBE &&
223
       dst->target != PIPE_TEXTURE_3D)
224
      assert(dstz == 0);
225
   dst_offset = i915_texture_offset(dst_tex, dst_level, dstz);
226
 
227
   if (src->target != PIPE_TEXTURE_CUBE &&
228
       src->target != PIPE_TEXTURE_3D)
229
      assert(src_box->z == 0);
230
   src_offset = i915_texture_offset(src_tex, src_level, src_box->z);
231
 
232
   assert( util_format_get_blocksize(dpt->format) == util_format_get_blocksize(spt->format) );
233
   assert( util_format_get_blockwidth(dpt->format) == util_format_get_blockwidth(spt->format) );
234
   assert( util_format_get_blockheight(dpt->format) == util_format_get_blockheight(spt->format) );
235
   assert( util_format_get_blockwidth(dpt->format) == 1 );
236
   assert( util_format_get_blockheight(dpt->format) == 1 );
237
 
238
   i915_copy_blit( i915_context(pipe),
239
                   util_format_get_blocksize(dpt->format),
240
                   (unsigned short) src_tex->stride, src_tex->buffer, src_offset,
241
                   (unsigned short) dst_tex->stride, dst_tex->buffer, dst_offset,
242
                   (short) src_box->x, (short) src_box->y, (short) dstx, (short) dsty,
243
                   (short) src_box->width, (short) src_box->height );
244
}
245
 
246
static void
247
i915_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info)
248
{
249
   struct i915_context *i915 = i915_context(pipe);
250
   struct pipe_blit_info info = *blit_info;
251
 
252
   if (util_try_blit_via_copy_region(pipe, &info)) {
253
      return; /* done */
254
   }
255
 
256
   if (info.mask & PIPE_MASK_S) {
257
      debug_printf("i915: cannot blit stencil, skipping\n");
258
      info.mask &= ~PIPE_MASK_S;
259
   }
260
 
261
   if (!util_blitter_is_blit_supported(i915->blitter, &info)) {
262
      debug_printf("i915: blit unsupported %s -> %s\n",
263
                   util_format_short_name(info.src.resource->format),
264
                   util_format_short_name(info.dst.resource->format));
265
      return;
266
   }
267
 
268
   i915_util_blitter_save_states(i915);
269
 
270
   util_blitter_blit(i915->blitter, &info);
271
}
272
 
273
static void
274
i915_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)
275
{
276
}
277
 
278
static void
279
i915_clear_render_target_blitter(struct pipe_context *pipe,
280
                                 struct pipe_surface *dst,
281
                                 const union pipe_color_union *color,
282
                                 unsigned dstx, unsigned dsty,
283
                                 unsigned width, unsigned height)
284
{
285
   struct i915_texture *tex = i915_texture(dst->texture);
286
   struct pipe_resource *pt = &tex->b.b;
287
   union util_color uc;
288
   unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);
289
 
290
   assert(util_format_get_blockwidth(pt->format) == 1);
291
   assert(util_format_get_blockheight(pt->format) == 1);
292
 
293
   util_pack_color(color->f, dst->format, &uc);
294
   i915_fill_blit( i915_context(pipe),
295
                   util_format_get_blocksize(pt->format),
296
                   XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB,
297
                   (unsigned short) tex->stride,
298
                   tex->buffer, offset,
299
                   (short) dstx, (short) dsty,
300
                   (short) width, (short) height,
301
                   uc.ui[0] );
302
}
303
 
304
static void
305
i915_clear_depth_stencil_blitter(struct pipe_context *pipe,
306
                                 struct pipe_surface *dst,
307
                                 unsigned clear_flags,
308
                                 double depth,
309
                                 unsigned stencil,
310
                                 unsigned dstx, unsigned dsty,
311
                                 unsigned width, unsigned height)
312
{
313
   struct i915_texture *tex = i915_texture(dst->texture);
314
   struct pipe_resource *pt = &tex->b.b;
315
   unsigned packedds;
316
   unsigned mask = 0;
317
   unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);
318
 
319
   assert(util_format_get_blockwidth(pt->format) == 1);
320
   assert(util_format_get_blockheight(pt->format) == 1);
321
 
322
   packedds = util_pack_z_stencil(dst->format, depth, stencil);
323
 
324
   if (clear_flags & PIPE_CLEAR_DEPTH)
325
      mask |= XY_COLOR_BLT_WRITE_RGB;
326
   /* XXX presumably this does read-modify-write
327
      (otherwise this won't work anyway). Hence will only want to
328
      do it if really have stencil and it isn't cleared */
329
   if ((clear_flags & PIPE_CLEAR_STENCIL) ||
330
       (dst->format != PIPE_FORMAT_Z24_UNORM_S8_UINT))
331
      mask |= XY_COLOR_BLT_WRITE_ALPHA;
332
 
333
   i915_fill_blit( i915_context(pipe),
334
                   util_format_get_blocksize(pt->format),
335
                   mask,
336
                   (unsigned short) tex->stride,
337
                   tex->buffer, offset,
338
                   (short) dstx, (short) dsty,
339
                   (short) width, (short) height,
340
                   packedds );
341
}
342
 
343
/*
344
 * Screen surface functions
345
 */
346
 
347
 
348
static struct pipe_surface *
349
i915_create_surface_custom(struct pipe_context *ctx,
350
                           struct pipe_resource *pt,
351
                           const struct pipe_surface *surf_tmpl,
352
                           unsigned width0,
353
                           unsigned height0)
354
{
355
   struct pipe_surface *ps;
356
 
357
   assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
358
   if (pt->target != PIPE_TEXTURE_CUBE &&
359
       pt->target != PIPE_TEXTURE_3D)
360
      assert(surf_tmpl->u.tex.first_layer == 0);
361
 
362
   ps = CALLOC_STRUCT(pipe_surface);
363
   if (ps) {
364
      /* could subclass pipe_surface and store offset as it used to do */
365
      pipe_reference_init(&ps->reference, 1);
366
      pipe_resource_reference(&ps->texture, pt);
367
      ps->format = surf_tmpl->format;
368
      ps->width = u_minify(width0, surf_tmpl->u.tex.level);
369
      ps->height = u_minify(height0, surf_tmpl->u.tex.level);
370
      ps->u.tex.level = surf_tmpl->u.tex.level;
371
      ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
372
      ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
373
      ps->context = ctx;
374
   }
375
   return ps;
376
}
377
 
378
static struct pipe_surface *
379
i915_create_surface(struct pipe_context *ctx,
380
                    struct pipe_resource *pt,
381
                    const struct pipe_surface *surf_tmpl)
382
{
383
   return i915_create_surface_custom(ctx, pt, surf_tmpl,
384
                                     pt->width0, pt->height0);
385
}
386
 
387
static void
388
i915_surface_destroy(struct pipe_context *ctx,
389
                     struct pipe_surface *surf)
390
{
391
   pipe_resource_reference(&surf->texture, NULL);
392
   FREE(surf);
393
}
394
 
395
 
396
void
397
i915_init_surface_functions(struct i915_context *i915)
398
{
399
   if (i915_screen(i915->base.screen)->debug.use_blitter) {
400
      i915->base.resource_copy_region = i915_surface_copy_blitter;
401
      i915->base.clear_render_target = i915_clear_render_target_blitter;
402
      i915->base.clear_depth_stencil = i915_clear_depth_stencil_blitter;
403
   } else {
404
      i915->base.resource_copy_region = i915_surface_copy_render;
405
      i915->base.clear_render_target = i915_clear_render_target_render;
406
      i915->base.clear_depth_stencil = i915_clear_depth_stencil_render;
407
   }
408
   i915->base.blit = i915_blit;
409
   i915->base.flush_resource = i915_flush_resource;
410
   i915->base.create_surface = i915_create_surface;
411
   i915->base.surface_destroy = i915_surface_destroy;
412
}