Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2009, VMware, Inc.
4
 * All Rights Reserved.
5
 * Copyright 2010 George Sapountzis 
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sub license, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 *
15
 * The above copyright notice and this permission notice (including the
16
 * next paragraph) shall be included in all copies or substantial portions
17
 * of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 *
27
 **************************************************************************/
28
 
29
/* TODO:
30
 *
31
 * xshm / EGLImage:
32
 *
33
 * Allow the loaders to use the XSHM extension. It probably requires callbacks
34
 * for createImage/destroyImage similar to DRI2 getBuffers.
35
 */
36
 
37
#include "util/u_format.h"
38
#include "util/u_memory.h"
39
#include "util/u_inlines.h"
40
#include "pipe/p_context.h"
41
#include "state_tracker/drisw_api.h"
42
#include "state_tracker/st_context.h"
43
 
44
#include "dri_screen.h"
45
#include "dri_context.h"
46
#include "dri_drawable.h"
47
 
48
DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE);
49
static boolean swrast_no_present = FALSE;
50
 
51
static INLINE void
52
get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h)
53
{
54
   __DRIscreen *sPriv = dPriv->driScreenPriv;
55
   const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
56
 
57
   loader->getDrawableInfo(dPriv,
58
                           x, y, w, h,
59
                           dPriv->loaderPrivate);
60
}
61
 
62
static INLINE void
63
put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height)
64
{
65
   __DRIscreen *sPriv = dPriv->driScreenPriv;
66
   const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
67
 
68
   loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
69
                    0, 0, width, height,
70
                    data, dPriv->loaderPrivate);
71
}
72
 
73
static INLINE void
74
get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data)
75
{
76
   __DRIscreen *sPriv = dPriv->driScreenPriv;
77
   const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
78
 
79
   loader->getImage(dPriv,
80
                    x, y, width, height,
81
                    data, dPriv->loaderPrivate);
82
}
83
 
84
static void
85
drisw_update_drawable_info(struct dri_drawable *drawable)
86
{
87
   __DRIdrawable *dPriv = drawable->dPriv;
88
   int x, y;
89
 
90
   get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h);
91
}
92
 
93
static void
94
drisw_put_image(struct dri_drawable *drawable,
95
                void *data, unsigned width, unsigned height)
96
{
97
   __DRIdrawable *dPriv = drawable->dPriv;
98
 
99
   put_image(dPriv, data, width, height);
100
}
101
 
102
static INLINE void
103
drisw_present_texture(__DRIdrawable *dPriv,
104
                      struct pipe_resource *ptex)
105
{
106
   struct dri_drawable *drawable = dri_drawable(dPriv);
107
   struct dri_screen *screen = dri_screen(drawable->sPriv);
108
 
109
   if (swrast_no_present)
110
      return;
111
 
112
   screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable);
113
}
114
 
115
static INLINE void
116
drisw_invalidate_drawable(__DRIdrawable *dPriv)
117
{
118
   struct dri_drawable *drawable = dri_drawable(dPriv);
119
 
120
   drawable->texture_stamp = dPriv->lastStamp - 1;
121
 
122
   p_atomic_inc(&drawable->base.stamp);
123
}
124
 
125
static INLINE void
126
drisw_copy_to_front(__DRIdrawable * dPriv,
127
                    struct pipe_resource *ptex)
128
{
129
   drisw_present_texture(dPriv, ptex);
130
 
131
   drisw_invalidate_drawable(dPriv);
132
}
133
 
134
/*
135
 * Backend functions for st_framebuffer interface and swap_buffers.
136
 */
137
 
138
static void
139
drisw_swap_buffers(__DRIdrawable *dPriv)
140
{
141
   struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv);
142
   struct dri_drawable *drawable = dri_drawable(dPriv);
143
   struct pipe_resource *ptex;
144
 
145
   if (!ctx)
146
      return;
147
 
148
   ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
149
 
150
   if (ptex) {
151
      if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL])
152
         pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
153
 
154
      ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
155
 
156
      drisw_copy_to_front(dPriv, ptex);
157
   }
158
}
159
 
160
static void
161
drisw_flush_frontbuffer(struct dri_context *ctx,
162
                        struct dri_drawable *drawable,
163
                        enum st_attachment_type statt)
164
{
165
   struct pipe_resource *ptex;
166
 
167
   if (!ctx)
168
      return;
169
 
170
   ptex = drawable->textures[statt];
171
 
172
   if (ptex) {
173
      drisw_copy_to_front(ctx->dPriv, ptex);
174
   }
175
}
176
 
177
/**
178
 * Allocate framebuffer attachments.
179
 *
180
 * During fixed-size operation, the function keeps allocating new attachments
181
 * as they are requested. Unused attachments are not removed, not until the
182
 * framebuffer is resized or destroyed.
183
 */
184
static void
185
drisw_allocate_textures(struct dri_context *stctx,
186
                        struct dri_drawable *drawable,
187
                        const enum st_attachment_type *statts,
188
                        unsigned count)
189
{
190
   struct dri_screen *screen = dri_screen(drawable->sPriv);
191
   struct pipe_resource templ;
192
   unsigned width, height;
193
   boolean resized;
194
   unsigned i;
195
 
196
   width  = drawable->dPriv->w;
197
   height = drawable->dPriv->h;
198
 
199
   resized = (drawable->old_w != width ||
200
              drawable->old_h != height);
201
 
202
   /* remove outdated textures */
203
   if (resized) {
204
      for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
205
         pipe_resource_reference(&drawable->textures[i], NULL);
206
   }
207
 
208
   memset(&templ, 0, sizeof(templ));
209
   templ.target = screen->target;
210
   templ.width0 = width;
211
   templ.height0 = height;
212
   templ.depth0 = 1;
213
   templ.array_size = 1;
214
   templ.last_level = 0;
215
 
216
   for (i = 0; i < count; i++) {
217
      enum pipe_format format;
218
      unsigned bind;
219
 
220
      /* the texture already exists or not requested */
221
      if (drawable->textures[statts[i]])
222
         continue;
223
 
224
      dri_drawable_get_format(drawable, statts[i], &format, &bind);
225
 
226
      /* if we don't do any present, no need for display targets */
227
      if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !swrast_no_present)
228
         bind |= PIPE_BIND_DISPLAY_TARGET;
229
 
230
      if (format == PIPE_FORMAT_NONE)
231
         continue;
232
 
233
      templ.format = format;
234
      templ.bind = bind;
235
 
236
      drawable->textures[statts[i]] =
237
         screen->base.screen->resource_create(screen->base.screen, &templ);
238
   }
239
 
240
   drawable->old_w = width;
241
   drawable->old_h = height;
242
}
243
 
244
static void
245
drisw_update_tex_buffer(struct dri_drawable *drawable,
246
                        struct dri_context *ctx,
247
                        struct pipe_resource *res)
248
{
249
   __DRIdrawable *dPriv = drawable->dPriv;
250
 
251
   struct st_context *st_ctx = (struct st_context *)ctx->st;
252
   struct pipe_context *pipe = st_ctx->pipe;
253
   struct pipe_transfer *transfer;
254
   char *map;
255
   int x, y, w, h;
256
   int ximage_stride, line;
257
   int cpp = util_format_get_blocksize(res->format);
258
 
259
   get_drawable_info(dPriv, &x, &y, &w, &h);
260
 
261
   map = pipe_transfer_map(pipe, res,
262
                           0, 0, // level, layer,
263
                           PIPE_TRANSFER_WRITE,
264
                           x, y, w, h, &transfer);
265
 
266
   /* Copy the Drawable content to the mapped texture buffer */
267
   get_image(dPriv, x, y, w, h, map);
268
 
269
   /* The pipe transfer has a pitch rounded up to the nearest 64 pixels.
270
      get_image() has a pitch rounded up to 4 bytes.  */
271
   ximage_stride = ((w * cpp) + 3) & -4;
272
   for (line = h-1; line; --line) {
273
      memmove(&map[line * transfer->stride],
274
              &map[line * ximage_stride],
275
              ximage_stride);
276
   }
277
 
278
   pipe_transfer_unmap(pipe, transfer);
279
}
280
 
281
/*
282
 * Backend function for init_screen.
283
 */
284
 
285
static const __DRIextension *drisw_screen_extensions[] = {
286
   &driTexBufferExtension.base,
287
   NULL
288
};
289
 
290
static struct drisw_loader_funcs drisw_lf = {
291
   .put_image = drisw_put_image
292
};
293
 
294
static const __DRIconfig **
295
drisw_init_screen(__DRIscreen * sPriv)
296
{
297
   const __DRIconfig **configs;
298
   struct dri_screen *screen;
299
   struct pipe_screen *pscreen;
300
 
301
   screen = CALLOC_STRUCT(dri_screen);
302
   if (!screen)
303
      return NULL;
304
 
305
   screen->sPriv = sPriv;
306
   screen->fd = -1;
307
 
308
   swrast_no_present = debug_get_option_swrast_no_present();
309
 
310
   sPriv->driverPrivate = (void *)screen;
311
   sPriv->extensions = drisw_screen_extensions;
312
 
313
   pscreen = drisw_create_screen(&drisw_lf);
314
   /* dri_init_screen_helper checks pscreen for us */
315
 
316
   configs = dri_init_screen_helper(screen, pscreen);
317
   if (!configs)
318
      goto fail;
319
 
320
   return configs;
321
fail:
322
   dri_destroy_screen_helper(screen);
323
   FREE(screen);
324
   return NULL;
325
}
326
 
327
static boolean
328
drisw_create_buffer(__DRIscreen * sPriv,
329
                    __DRIdrawable * dPriv,
330
                    const struct gl_config * visual, boolean isPixmap)
331
{
332
   struct dri_drawable *drawable = NULL;
333
 
334
   if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
335
      return FALSE;
336
 
337
   drawable = dPriv->driverPrivate;
338
 
339
   drawable->allocate_textures = drisw_allocate_textures;
340
   drawable->update_drawable_info = drisw_update_drawable_info;
341
   drawable->flush_frontbuffer = drisw_flush_frontbuffer;
342
   drawable->update_tex_buffer = drisw_update_tex_buffer;
343
 
344
   return TRUE;
345
}
346
 
347
/**
348
 * DRI driver virtual function table.
349
 *
350
 * DRI versions differ in their implementation of init_screen and swap_buffers.
351
 */
352
const struct __DriverAPIRec driDriverAPI = {
353
   .InitScreen = drisw_init_screen,
354
   .DestroyScreen = dri_destroy_screen,
355
   .CreateContext = dri_create_context,
356
   .DestroyContext = dri_destroy_context,
357
   .CreateBuffer = drisw_create_buffer,
358
   .DestroyBuffer = dri_destroy_buffer,
359
   .SwapBuffers = drisw_swap_buffers,
360
   .MakeCurrent = dri_make_current,
361
   .UnbindContext = dri_unbind_context,
362
};
363
 
364
/* This is the table of extensions that the loader will dlsym() for. */
365
PUBLIC const __DRIextension *__driDriverExtensions[] = {
366
    &driCoreExtension.base,
367
    &driSWRastExtension.base,
368
    NULL
369
};
370
 
371
/* vim: set sw=3 ts=8 sts=3 expandtab: */