00849985d6b99d47875556d75585255eb44a5bca
[mesa.git] / src / gallium / winsys / sw / dri / dri_sw_winsys.c
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 *
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 *
67 dri_sw_winsys( struct sw_winsys *ws )
68 {
69 return (struct dri_sw_winsys *)ws;
70 }
71
72
73 static boolean
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 *
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
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 *
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
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 *
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
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
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 = (char *)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
212 dri_destroy_sw_winsys(struct sw_winsys *winsys)
213 {
214 FREE(winsys);
215 }
216
217 struct sw_winsys *
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: */