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
 * Copyright 2010 VMware, Inc.  All rights reserved.
3
 *
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use, copy,
8
 * modify, merge, publish, distribute, sublicense, and/or sell copies
9
 * of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 *
24
 **********************************************************/
25
 
26
 
27
#include "wrapper_sw_winsys.h"
28
 
29
#include "pipe/p_format.h"
30
#include "pipe/p_state.h"
31
 
32
#include "state_tracker/sw_winsys.h"
33
 
34
#include "util/u_memory.h"
35
#include "util/u_inlines.h"
36
 
37
/*
38
 * This code wraps a pipe_screen and exposes a sw_winsys interface for use
39
 * with software resterizers. This code is used by the DRM based winsys to
40
 * allow access to the drm driver.
41
 *
42
 * We must borrow the whole stack because only the pipe screen knows how
43
 * to decode the content of a buffer. Or how to create a buffer that
44
 * can still be used by drivers using real hardware (as the case is
45
 * with software st/xorg but hw st/dri).
46
 *
47
 * We also need a pipe context for the transfers.
48
 */
49
 
50
struct wrapper_sw_winsys
51
{
52
   struct sw_winsys base;
53
   struct pipe_screen *screen;
54
   struct pipe_context *pipe;
55
   enum pipe_texture_target target;
56
};
57
 
58
struct wrapper_sw_displaytarget
59
{
60
   struct wrapper_sw_winsys *winsys;
61
   struct pipe_resource *tex;
62
   struct pipe_transfer *transfer;
63
 
64
   unsigned map_count;
65
   unsigned stride; /**< because we get stride at create */
66
   void *ptr;
67
};
68
 
69
static INLINE struct wrapper_sw_winsys *
70
wrapper_sw_winsys(struct sw_winsys *ws)
71
{
72
   return (struct wrapper_sw_winsys *)ws;
73
}
74
 
75
static INLINE struct wrapper_sw_displaytarget *
76
wrapper_sw_displaytarget(struct sw_displaytarget *dt)
77
{
78
   return (struct wrapper_sw_displaytarget *)dt;
79
}
80
 
81
 
82
/*
83
 * Functions
84
 */
85
 
86
 
87
static boolean
88
wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride)
89
{
90
   struct pipe_context *pipe = wdt->winsys->pipe;
91
   struct pipe_resource *tex = wdt->tex;
92
   struct pipe_transfer *tr;
93
   void *map;
94
 
95
   map = pipe_transfer_map(pipe, tex, 0, 0,
96
                           PIPE_TRANSFER_READ_WRITE,
97
                           0, 0, wdt->tex->width0, wdt->tex->height0, &tr);
98
   if (!map)
99
      return FALSE;
100
 
101
   *stride = tr->stride;
102
   wdt->stride = tr->stride;
103
 
104
   pipe->transfer_unmap(pipe, tr);
105
 
106
   return TRUE;
107
}
108
 
109
static struct sw_displaytarget *
110
wsw_dt_wrap_texture(struct wrapper_sw_winsys *wsw,
111
                    struct pipe_resource *tex, unsigned *stride)
112
{
113
   struct wrapper_sw_displaytarget *wdt = CALLOC_STRUCT(wrapper_sw_displaytarget);
114
   if (!wdt)
115
      goto err_unref;
116
 
117
   wdt->tex = tex;
118
   wdt->winsys = wsw;
119
 
120
   if (!wsw_dt_get_stride(wdt, stride))
121
      goto err_free;
122
 
123
   return (struct sw_displaytarget *)wdt;
124
 
125
err_free:
126
   FREE(wdt);
127
err_unref:
128
   pipe_resource_reference(&tex, NULL);
129
   return NULL;
130
}
131
 
132
static struct sw_displaytarget *
133
wsw_dt_create(struct sw_winsys *ws,
134
              unsigned bind,
135
              enum pipe_format format,
136
              unsigned width, unsigned height,
137
              unsigned alignment,
138
              unsigned *stride)
139
{
140
   struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
141
   struct pipe_resource templ;
142
   struct pipe_resource *tex;
143
 
144
   /*
145
    * XXX Why don't we just get the template.
146
    */
147
   memset(&templ, 0, sizeof(templ));
148
   templ.target = wsw->target;
149
   templ.width0 = width;
150
   templ.height0 = height;
151
   templ.depth0 = 1;
152
   templ.array_size = 1;
153
   templ.format = format;
154
   templ.bind = bind;
155
 
156
   /* XXX alignment: we can't do anything about this */
157
 
158
   tex = wsw->screen->resource_create(wsw->screen, &templ);
159
   if (!tex)
160
      return NULL;
161
 
162
   return wsw_dt_wrap_texture(wsw, tex, stride);
163
}
164
 
165
static struct sw_displaytarget *
166
wsw_dt_from_handle(struct sw_winsys *ws,
167
                   const struct pipe_resource *templ,
168
                   struct winsys_handle *whandle,
169
                   unsigned *stride)
170
{
171
   struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
172
   struct pipe_resource *tex;
173
 
174
   tex = wsw->screen->resource_from_handle(wsw->screen, templ, whandle);
175
   if (!tex)
176
      return NULL;
177
 
178
   return wsw_dt_wrap_texture(wsw, tex, stride);
179
}
180
 
181
static boolean
182
wsw_dt_get_handle(struct sw_winsys *ws,
183
                  struct sw_displaytarget *dt,
184
                  struct winsys_handle *whandle)
185
{
186
   struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
187
   struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
188
   struct pipe_resource *tex = wdt->tex;
189
 
190
   return wsw->screen->resource_get_handle(wsw->screen, tex, whandle);
191
}
192
 
193
static void *
194
wsw_dt_map(struct sw_winsys *ws,
195
           struct sw_displaytarget *dt,
196
           unsigned flags)
197
{
198
   struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
199
   struct pipe_context *pipe = wdt->winsys->pipe;
200
   struct pipe_resource *tex = wdt->tex;
201
   struct pipe_transfer *tr;
202
   void *ptr;
203
 
204
   if (!wdt->map_count) {
205
 
206
      assert(!wdt->transfer);
207
 
208
      ptr = pipe_transfer_map(pipe, tex, 0, 0,
209
                              PIPE_TRANSFER_READ_WRITE,
210
                              0, 0, wdt->tex->width0, wdt->tex->height0, &tr);
211
      if (!ptr)
212
        goto err;
213
 
214
      wdt->transfer = tr;
215
      wdt->ptr = ptr;
216
 
217
      /* XXX Handle this case */
218
      assert(tr->stride == wdt->stride);
219
   }
220
 
221
   wdt->map_count++;
222
 
223
   return wdt->ptr;
224
 
225
err:
226
   pipe->transfer_unmap(pipe, tr);
227
   return NULL;
228
}
229
 
230
static void
231
wsw_dt_unmap(struct sw_winsys *ws,
232
             struct sw_displaytarget *dt)
233
{
234
   struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
235
   struct pipe_context *pipe = wdt->winsys->pipe;
236
 
237
   assert(wdt->transfer);
238
 
239
   wdt->map_count--;
240
 
241
   if (wdt->map_count)
242
      return;
243
 
244
   pipe->transfer_unmap(pipe, wdt->transfer);
245
   pipe->flush(pipe, NULL, 0);
246
   wdt->transfer = NULL;
247
}
248
 
249
static void
250
wsw_dt_destroy(struct sw_winsys *ws,
251
               struct sw_displaytarget *dt)
252
{
253
   struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
254
 
255
   pipe_resource_reference(&wdt->tex, NULL);
256
 
257
   FREE(wdt);
258
}
259
 
260
static void
261
wsw_destroy(struct sw_winsys *ws)
262
{
263
   struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
264
 
265
   wsw->pipe->destroy(wsw->pipe);
266
   wsw->screen->destroy(wsw->screen);
267
 
268
   FREE(wsw);
269
}
270
 
271
struct sw_winsys *
272
wrapper_sw_winsys_wrap_pipe_screen(struct pipe_screen *screen)
273
{
274
   struct wrapper_sw_winsys *wsw = CALLOC_STRUCT(wrapper_sw_winsys);
275
 
276
   if (!wsw)
277
      goto err;
278
 
279
   wsw->base.displaytarget_create = wsw_dt_create;
280
   wsw->base.displaytarget_from_handle = wsw_dt_from_handle;
281
   wsw->base.displaytarget_get_handle = wsw_dt_get_handle;
282
   wsw->base.displaytarget_map = wsw_dt_map;
283
   wsw->base.displaytarget_unmap = wsw_dt_unmap;
284
   wsw->base.displaytarget_destroy = wsw_dt_destroy;
285
   wsw->base.destroy = wsw_destroy;
286
 
287
   wsw->screen = screen;
288
   wsw->pipe = screen->context_create(screen, NULL);
289
   if (!wsw->pipe)
290
      goto err_free;
291
 
292
   if(screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES))
293
      wsw->target = PIPE_TEXTURE_2D;
294
   else
295
      wsw->target = PIPE_TEXTURE_RECT;
296
 
297
   return &wsw->base;
298
 
299
err_free:
300
   FREE(wsw);
301
err:
302
   return NULL;
303
}
304
 
305
struct pipe_screen *
306
wrapper_sw_winsys_dewrap_pipe_screen(struct sw_winsys *ws)
307
{
308
   struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
309
   struct pipe_screen *screen = wsw->screen;
310
 
311
   wsw->pipe->destroy(wsw->pipe);
312
   /* don't destroy the screen its needed later on */
313
 
314
   FREE(wsw);
315
   return screen;
316
}