1 /**************************************************************************
2  *
3  * Copyright 2009, VMware, Inc.
4  * All Rights Reserved.
5  * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
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 #include "pipe/p_compiler.h"
30 #include "pipe/p_format.h"
31 #include "util/u_inlines.h"
32 #include "util/u_format.h"
33 #include "util/u_math.h"
34 #include "util/u_memory.h"
35 
36 #include "state_tracker/sw_winsys.h"
37 #include "dri_sw_winsys.h"
38 
39 
40 struct dri_sw_displaytarget
41 {
42    enum pipe_format format;
43    unsigned width;
44    unsigned height;
45    unsigned stride;
46 
47    unsigned map_flags;
48    void *data;
49    void *mapped;
50    const void *front_private;
51 };
52 
53 struct dri_sw_winsys
54 {
55    struct sw_winsys base;
56 
57    struct drisw_loader_funcs *lf;
58 };
59 
60 static inline struct dri_sw_displaytarget *
dri_sw_displaytarget(struct sw_displaytarget * dt)61 dri_sw_displaytarget( struct sw_displaytarget *dt )
62 {
63    return (struct dri_sw_displaytarget *)dt;
64 }
65 
66 static inline struct dri_sw_winsys *
dri_sw_winsys(struct sw_winsys * ws)67 dri_sw_winsys( struct sw_winsys *ws )
68 {
69    return (struct dri_sw_winsys *)ws;
70 }
71 
72 
73 static boolean
dri_sw_is_displaytarget_format_supported(struct sw_winsys * ws,unsigned tex_usage,enum pipe_format format)74 dri_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
75                                           unsigned tex_usage,
76                                           enum pipe_format format )
77 {
78    /* TODO: check visuals or other sensible thing here */
79    return TRUE;
80 }
81 
82 static struct sw_displaytarget *
dri_sw_displaytarget_create(struct sw_winsys * winsys,unsigned tex_usage,enum pipe_format format,unsigned width,unsigned height,unsigned alignment,const void * front_private,unsigned * stride)83 dri_sw_displaytarget_create(struct sw_winsys *winsys,
84                             unsigned tex_usage,
85                             enum pipe_format format,
86                             unsigned width, unsigned height,
87                             unsigned alignment,
88                             const void *front_private,
89                             unsigned *stride)
90 {
91    struct dri_sw_displaytarget *dri_sw_dt;
92    unsigned nblocksy, size, format_stride;
93 
94    dri_sw_dt = CALLOC_STRUCT(dri_sw_displaytarget);
95    if(!dri_sw_dt)
96       goto no_dt;
97 
98    dri_sw_dt->format = format;
99    dri_sw_dt->width = width;
100    dri_sw_dt->height = height;
101    dri_sw_dt->front_private = front_private;
102 
103    format_stride = util_format_get_stride(format, width);
104    dri_sw_dt->stride = align(format_stride, alignment);
105 
106    nblocksy = util_format_get_nblocksy(format, height);
107    size = dri_sw_dt->stride * nblocksy;
108 
109    dri_sw_dt->data = align_malloc(size, alignment);
110    if(!dri_sw_dt->data)
111       goto no_data;
112 
113    *stride = dri_sw_dt->stride;
114    return (struct sw_displaytarget *)dri_sw_dt;
115 
116 no_data:
117    FREE(dri_sw_dt);
118 no_dt:
119    return NULL;
120 }
121 
122 static void
dri_sw_displaytarget_destroy(struct sw_winsys * ws,struct sw_displaytarget * dt)123 dri_sw_displaytarget_destroy(struct sw_winsys *ws,
124                              struct sw_displaytarget *dt)
125 {
126    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
127 
128    align_free(dri_sw_dt->data);
129 
130    FREE(dri_sw_dt);
131 }
132 
133 static void *
dri_sw_displaytarget_map(struct sw_winsys * ws,struct sw_displaytarget * dt,unsigned flags)134 dri_sw_displaytarget_map(struct sw_winsys *ws,
135                          struct sw_displaytarget *dt,
136                          unsigned flags)
137 {
138    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
139    dri_sw_dt->mapped = dri_sw_dt->data;
140 
141    if (dri_sw_dt->front_private && (flags & PIPE_TRANSFER_READ)) {
142       struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
143       dri_sw_ws->lf->get_image((void *)dri_sw_dt->front_private, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride, dri_sw_dt->data);
144    }
145    dri_sw_dt->map_flags = flags;
146    return dri_sw_dt->mapped;
147 }
148 
149 static void
dri_sw_displaytarget_unmap(struct sw_winsys * ws,struct sw_displaytarget * dt)150 dri_sw_displaytarget_unmap(struct sw_winsys *ws,
151                            struct sw_displaytarget *dt)
152 {
153    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
154    if (dri_sw_dt->front_private && (dri_sw_dt->map_flags & PIPE_TRANSFER_WRITE)) {
155       struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
156       dri_sw_ws->lf->put_image2((void *)dri_sw_dt->front_private, dri_sw_dt->data, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride);
157    }
158    dri_sw_dt->map_flags = 0;
159    dri_sw_dt->mapped = NULL;
160 }
161 
162 static struct sw_displaytarget *
dri_sw_displaytarget_from_handle(struct sw_winsys * winsys,const struct pipe_resource * templ,struct winsys_handle * whandle,unsigned * stride)163 dri_sw_displaytarget_from_handle(struct sw_winsys *winsys,
164                                  const struct pipe_resource *templ,
165                                  struct winsys_handle *whandle,
166                                  unsigned *stride)
167 {
168    assert(0);
169    return NULL;
170 }
171 
172 static boolean
dri_sw_displaytarget_get_handle(struct sw_winsys * winsys,struct sw_displaytarget * dt,struct winsys_handle * whandle)173 dri_sw_displaytarget_get_handle(struct sw_winsys *winsys,
174                                 struct sw_displaytarget *dt,
175                                 struct winsys_handle *whandle)
176 {
177    assert(0);
178    return FALSE;
179 }
180 
181 static void
dri_sw_displaytarget_display(struct sw_winsys * ws,struct sw_displaytarget * dt,void * context_private,struct pipe_box * box)182 dri_sw_displaytarget_display(struct sw_winsys *ws,
183                              struct sw_displaytarget *dt,
184                              void *context_private,
185                              struct pipe_box *box)
186 {
187    struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
188    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
189    struct dri_drawable *dri_drawable = (struct dri_drawable *)context_private;
190    unsigned width, height;
191    unsigned blsize = util_format_get_blocksize(dri_sw_dt->format);
192 
193    /* Set the width to 'stride / cpp'.
194     *
195     * PutImage correctly clips to the width of the dst drawable.
196     */
197    width = dri_sw_dt->stride / blsize;
198 
199    height = dri_sw_dt->height;
200 
201    if (box) {
202        void *data;
203        data = dri_sw_dt->data + (dri_sw_dt->stride * box->y) + box->x * blsize;
204        dri_sw_ws->lf->put_image2(dri_drawable, data,
205                                  box->x, box->y, box->width, box->height, dri_sw_dt->stride);
206    } else {
207        dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
208    }
209 }
210 
211 static void
dri_destroy_sw_winsys(struct sw_winsys * winsys)212 dri_destroy_sw_winsys(struct sw_winsys *winsys)
213 {
214    FREE(winsys);
215 }
216 
217 struct sw_winsys *
dri_create_sw_winsys(struct drisw_loader_funcs * lf)218 dri_create_sw_winsys(struct drisw_loader_funcs *lf)
219 {
220    struct dri_sw_winsys *ws;
221 
222    ws = CALLOC_STRUCT(dri_sw_winsys);
223    if (!ws)
224       return NULL;
225 
226    ws->lf = lf;
227    ws->base.destroy = dri_destroy_sw_winsys;
228 
229    ws->base.is_displaytarget_format_supported = dri_sw_is_displaytarget_format_supported;
230 
231    /* screen texture functions */
232    ws->base.displaytarget_create = dri_sw_displaytarget_create;
233    ws->base.displaytarget_destroy = dri_sw_displaytarget_destroy;
234    ws->base.displaytarget_from_handle = dri_sw_displaytarget_from_handle;
235    ws->base.displaytarget_get_handle = dri_sw_displaytarget_get_handle;
236 
237    /* texture functions */
238    ws->base.displaytarget_map = dri_sw_displaytarget_map;
239    ws->base.displaytarget_unmap = dri_sw_displaytarget_unmap;
240 
241    ws->base.displaytarget_display = dri_sw_displaytarget_display;
242 
243    return &ws->base;
244 }
245 
246 /* vim: set sw=3 ts=8 sts=3 expandtab: */
247