Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 2010 LunarG Inc. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
22 | * DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Chia-I Wu |
||
26 | */ |
||
27 | |||
28 | #include |
||
29 | #include |
||
30 | #include |
||
31 | |||
32 | #include "pipe/p_compiler.h" |
||
33 | #include "util/u_format.h" |
||
34 | #include "util/u_math.h" |
||
35 | #include "util/u_memory.h" |
||
36 | #include "state_tracker/sw_winsys.h" |
||
37 | |||
38 | #include "fbdev_sw_winsys.h" |
||
39 | |||
40 | struct fbdev_sw_displaytarget |
||
41 | { |
||
42 | enum pipe_format format; |
||
43 | unsigned width; |
||
44 | unsigned height; |
||
45 | unsigned stride; |
||
46 | |||
47 | void *data; |
||
48 | void *mapped; |
||
49 | }; |
||
50 | |||
51 | struct fbdev_sw_winsys |
||
52 | { |
||
53 | struct sw_winsys base; |
||
54 | |||
55 | int fd; |
||
56 | |||
57 | struct fb_fix_screeninfo finfo; |
||
58 | unsigned rows; |
||
59 | unsigned stride; |
||
60 | }; |
||
61 | |||
62 | static INLINE struct fbdev_sw_displaytarget * |
||
63 | fbdev_sw_displaytarget(struct sw_displaytarget *dt) |
||
64 | { |
||
65 | return (struct fbdev_sw_displaytarget *) dt; |
||
66 | } |
||
67 | |||
68 | static INLINE struct fbdev_sw_winsys * |
||
69 | fbdev_sw_winsys(struct sw_winsys *ws) |
||
70 | { |
||
71 | return (struct fbdev_sw_winsys *) ws; |
||
72 | } |
||
73 | |||
74 | static void |
||
75 | fbdev_displaytarget_display(struct sw_winsys *ws, |
||
76 | struct sw_displaytarget *dt, |
||
77 | void *winsys_private) |
||
78 | { |
||
79 | struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws); |
||
80 | struct fbdev_sw_displaytarget *src = fbdev_sw_displaytarget(dt); |
||
81 | const struct fbdev_sw_drawable *dst = |
||
82 | (const struct fbdev_sw_drawable *) winsys_private; |
||
83 | unsigned height, row_offset, row_len, i; |
||
84 | void *fbmem; |
||
85 | |||
86 | /* FIXME format conversion */ |
||
87 | if (dst->format != src->format) { |
||
88 | assert(0); |
||
89 | return; |
||
90 | } |
||
91 | |||
92 | height = dst->height; |
||
93 | if (dst->y + dst->height > fbdev->rows) { |
||
94 | /* nothing to copy */ |
||
95 | if (dst->y >= fbdev->rows) |
||
96 | return; |
||
97 | |||
98 | height = fbdev->rows - dst->y; |
||
99 | } |
||
100 | |||
101 | row_offset = util_format_get_stride(dst->format, dst->x); |
||
102 | row_len = util_format_get_stride(dst->format, dst->width); |
||
103 | if (row_offset + row_len > fbdev->stride) { |
||
104 | /* nothing to copy */ |
||
105 | if (row_offset >= fbdev->stride) |
||
106 | return; |
||
107 | |||
108 | row_len = fbdev->stride - row_offset; |
||
109 | } |
||
110 | |||
111 | fbmem = mmap(0, fbdev->finfo.smem_len, |
||
112 | PROT_WRITE, MAP_SHARED, fbdev->fd, 0); |
||
113 | if (fbmem == MAP_FAILED) |
||
114 | return; |
||
115 | |||
116 | for (i = 0; i < height; i++) { |
||
117 | char *from = (char *) src->data + src->stride * i; |
||
118 | char *to = (char *) fbmem + fbdev->stride * (dst->y + i) + row_offset; |
||
119 | |||
120 | memcpy(to, from, row_len); |
||
121 | } |
||
122 | |||
123 | munmap(fbmem, fbdev->finfo.smem_len); |
||
124 | } |
||
125 | |||
126 | static void |
||
127 | fbdev_displaytarget_unmap(struct sw_winsys *ws, |
||
128 | struct sw_displaytarget *dt) |
||
129 | { |
||
130 | struct fbdev_sw_displaytarget *fbdt = fbdev_sw_displaytarget(dt); |
||
131 | fbdt->mapped = NULL; |
||
132 | } |
||
133 | |||
134 | static void * |
||
135 | fbdev_displaytarget_map(struct sw_winsys *ws, |
||
136 | struct sw_displaytarget *dt, |
||
137 | unsigned flags) |
||
138 | { |
||
139 | struct fbdev_sw_displaytarget *fbdt = fbdev_sw_displaytarget(dt); |
||
140 | fbdt->mapped = fbdt->data; |
||
141 | return fbdt->mapped; |
||
142 | } |
||
143 | |||
144 | static void |
||
145 | fbdev_displaytarget_destroy(struct sw_winsys *ws, |
||
146 | struct sw_displaytarget *dt) |
||
147 | { |
||
148 | struct fbdev_sw_displaytarget *fbdt = fbdev_sw_displaytarget(dt); |
||
149 | |||
150 | if (fbdt->data) |
||
151 | align_free(fbdt->data); |
||
152 | |||
153 | FREE(fbdt); |
||
154 | } |
||
155 | |||
156 | static struct sw_displaytarget * |
||
157 | fbdev_displaytarget_create(struct sw_winsys *ws, |
||
158 | unsigned tex_usage, |
||
159 | enum pipe_format format, |
||
160 | unsigned width, unsigned height, |
||
161 | unsigned alignment, |
||
162 | unsigned *stride) |
||
163 | { |
||
164 | struct fbdev_sw_displaytarget *fbdt; |
||
165 | unsigned nblocksy, size, format_stride; |
||
166 | |||
167 | fbdt = CALLOC_STRUCT(fbdev_sw_displaytarget); |
||
168 | if (!fbdt) |
||
169 | return NULL; |
||
170 | |||
171 | fbdt->format = format; |
||
172 | fbdt->width = width; |
||
173 | fbdt->height = height; |
||
174 | |||
175 | format_stride = util_format_get_stride(format, width); |
||
176 | fbdt->stride = align(format_stride, alignment); |
||
177 | |||
178 | nblocksy = util_format_get_nblocksy(format, height); |
||
179 | size = fbdt->stride * nblocksy; |
||
180 | |||
181 | fbdt->data = align_malloc(size, alignment); |
||
182 | if (!fbdt->data) { |
||
183 | FREE(fbdt); |
||
184 | return NULL; |
||
185 | } |
||
186 | |||
187 | *stride = fbdt->stride; |
||
188 | |||
189 | return (struct sw_displaytarget *) fbdt; |
||
190 | } |
||
191 | |||
192 | static boolean |
||
193 | fbdev_is_displaytarget_format_supported(struct sw_winsys *ws, |
||
194 | unsigned tex_usage, |
||
195 | enum pipe_format format) |
||
196 | { |
||
197 | return TRUE; |
||
198 | } |
||
199 | |||
200 | static void |
||
201 | fbdev_destroy(struct sw_winsys *ws) |
||
202 | { |
||
203 | struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws); |
||
204 | |||
205 | FREE(fbdev); |
||
206 | } |
||
207 | |||
208 | struct sw_winsys * |
||
209 | fbdev_create_sw_winsys(int fd) |
||
210 | { |
||
211 | struct fbdev_sw_winsys *fbdev; |
||
212 | |||
213 | fbdev = CALLOC_STRUCT(fbdev_sw_winsys); |
||
214 | if (!fbdev) |
||
215 | return NULL; |
||
216 | |||
217 | fbdev->fd = fd; |
||
218 | if (ioctl(fbdev->fd, FBIOGET_FSCREENINFO, &fbdev->finfo)) { |
||
219 | FREE(fbdev); |
||
220 | return NULL; |
||
221 | } |
||
222 | |||
223 | fbdev->rows = fbdev->finfo.smem_len / fbdev->finfo.line_length; |
||
224 | fbdev->stride = fbdev->finfo.line_length; |
||
225 | |||
226 | fbdev->base.destroy = fbdev_destroy; |
||
227 | fbdev->base.is_displaytarget_format_supported = |
||
228 | fbdev_is_displaytarget_format_supported; |
||
229 | |||
230 | fbdev->base.displaytarget_create = fbdev_displaytarget_create; |
||
231 | fbdev->base.displaytarget_destroy = fbdev_displaytarget_destroy; |
||
232 | fbdev->base.displaytarget_map = fbdev_displaytarget_map; |
||
233 | fbdev->base.displaytarget_unmap = fbdev_displaytarget_unmap; |
||
234 | |||
235 | fbdev->base.displaytarget_display = fbdev_displaytarget_display; |
||
236 | |||
237 | return &fbdev->base; |
||
238 | }> |