summaryrefslogtreecommitdiff
path: root/src/lib/ector/software/ector_software_buffer.c
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2015-12-11 18:49:16 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2016-01-05 15:43:43 +0900
commit1f25b523b462309534e2fd8e59ffb62747cc6224 (patch)
treea7756b0c33e7a2e37c8b8bc7cc86b638d42a8a6f /src/lib/ector/software/ector_software_buffer.c
parent5e075c193c51201071b8efc950b49b45b9caa92c (diff)
ector buffer: add COW access mode
In case you map a buffer once for read-only and once for write, we can generate a temporary copy and return that instead. This buffer will be copied back to the original surface once the COW surface is unmapped.
Diffstat (limited to 'src/lib/ector/software/ector_software_buffer.c')
-rw-r--r--src/lib/ector/software/ector_software_buffer.c86
1 files changed, 80 insertions, 6 deletions
diff --git a/src/lib/ector/software/ector_software_buffer.c b/src/lib/ector/software/ector_software_buffer.c
index e64234d4de..f96d05ad17 100644
--- a/src/lib/ector/software/ector_software_buffer.c
+++ b/src/lib/ector/software/ector_software_buffer.c
@@ -15,9 +15,12 @@
15typedef struct _Ector_Software_Buffer_Map 15typedef struct _Ector_Software_Buffer_Map
16{ 16{
17 EINA_INLIST; 17 EINA_INLIST;
18 void *ptr; 18 uint8_t *ptr;
19 unsigned int size; // in bytes 19 unsigned int size; // in bytes
20 unsigned int x, y, w, h;
21 Efl_Gfx_Colorspace cspace;
20 Eina_Bool allocated; 22 Eina_Bool allocated;
23 Ector_Buffer_Access_Flag mode;
21} Ector_Software_Buffer_Map; 24} Ector_Software_Buffer_Map;
22 25
23static inline int 26static inline int
@@ -84,6 +87,12 @@ _ector_software_buffer_base_ector_generic_buffer_pixels_set(Eo *obj, Ector_Softw
84 return EINA_FALSE; 87 return EINA_FALSE;
85 } 88 }
86 89
90 if (pd->internal.maps)
91 {
92 ERR("Can not call pixels_set when the buffer is mapped.");
93 return EINA_FALSE;
94 }
95
87 // safety check 96 // safety check
88 px = _min_stride_calc(1, cspace); 97 px = _min_stride_calc(1, cspace);
89 if (px && ((unsigned long long)(uintptr_t)pixels) & (px - 1)) 98 if (px && ((unsigned long long)(uintptr_t)pixels) & (px - 1))
@@ -143,7 +152,8 @@ _ector_software_buffer_base_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_
143 Efl_Gfx_Colorspace cspace EINA_UNUSED, unsigned int *stride) 152 Efl_Gfx_Colorspace cspace EINA_UNUSED, unsigned int *stride)
144{ 153{
145 Ector_Software_Buffer_Map *map = NULL; 154 Ector_Software_Buffer_Map *map = NULL;
146 unsigned int off, k; 155 Eina_Bool need_cow = EINA_FALSE;
156 unsigned int off, k, dst_stride;
147 157
148 if (!w) w = pd->generic->w; 158 if (!w) w = pd->generic->w;
149 if (!h) h = pd->generic->h; 159 if (!h) h = pd->generic->h;
@@ -158,10 +168,29 @@ _ector_software_buffer_base_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_
158 if ((mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) && !pd->writable) 168 if ((mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) && !pd->writable)
159 fail("Can not map a read-only buffer for writing"); 169 fail("Can not map a read-only buffer for writing");
160 170
171 if ((mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) &&
172 (mode & ECTOR_BUFFER_ACCESS_FLAG_COW))
173 {
174 EINA_INLIST_FOREACH(pd->internal.maps, map)
175 if (map->mode == ECTOR_BUFFER_ACCESS_FLAG_READ)
176 {
177 need_cow = EINA_TRUE;
178 break;
179 }
180 }
181
161 map = calloc(1, sizeof(*map)); 182 map = calloc(1, sizeof(*map));
162 if (!map) fail("Out of memory"); 183 if (!map) fail("Out of memory");
163 184
185 map->mode = mode;
186 map->cspace = cspace;
187 map->x = x;
188 map->y = y;
189 map->w = w;
190 map->h = h;
191
164 off = _min_stride_calc(x + pd->generic->l, pd->generic->cspace) + (pd->stride * (y + pd->generic->t)); 192 off = _min_stride_calc(x + pd->generic->l, pd->generic->cspace) + (pd->stride * (y + pd->generic->t));
193 dst_stride = _min_stride_calc(w, cspace);
165 194
166 if (cspace != pd->generic->cspace) 195 if (cspace != pd->generic->cspace)
167 { 196 {
@@ -170,7 +199,6 @@ _ector_software_buffer_base_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_
170 map->allocated = EINA_TRUE; 199 map->allocated = EINA_TRUE;
171 map->ptr = malloc(map->size); 200 map->ptr = malloc(map->size);
172 if (!map->ptr) fail("Out of memory"); 201 if (!map->ptr) fail("Out of memory");
173 if (stride) *stride = _min_stride_calc(w, cspace);
174 202
175 if (cspace == EFL_GFX_COLORSPACE_ARGB8888) 203 if (cspace == EFL_GFX_COLORSPACE_ARGB8888)
176 { 204 {
@@ -180,18 +208,30 @@ _ector_software_buffer_base_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_
180 else 208 else
181 { 209 {
182 for (k = 0; k < h; k++) 210 for (k = 0; k < h; k++)
183 _pixels_argb_to_gry8_convert((uint8_t *) map->ptr + (k * w), (uint32_t *) (pd->pixels.u8 + off + (k * pd->stride)), w); 211 _pixels_argb_to_gry8_convert(map->ptr + (k * w), (uint32_t *) (pd->pixels.u8 + off + (k * pd->stride)), w);
184 } 212 }
185 } 213 }
214 else if (need_cow)
215 {
216 // copy-on-write access
217 map->size = _min_stride_calc(w, cspace) * h;
218 map->allocated = EINA_TRUE;
219 map->ptr = malloc(map->size);
220 if (!map->ptr) fail("Out of memory");
221 for (k = 0; k < h; k++)
222 memcpy(map->ptr + k * dst_stride, pd->pixels.u8 + x + (k + y) * pd->stride, dst_stride);
223 }
186 else 224 else
187 { 225 {
226 // direct access, zero-copy
188 map->size = (pd->stride * h) - off; 227 map->size = (pd->stride * h) - off;
189 map->ptr = pd->pixels.u8 + off; 228 map->ptr = pd->pixels.u8 + off;
190 if (stride) *stride = pd->stride; 229 dst_stride = pd->stride;
191 } 230 }
192 231
193 pd->internal.maps = eina_inlist_prepend(pd->internal.maps, EINA_INLIST_GET(map)); 232 pd->internal.maps = eina_inlist_prepend(pd->internal.maps, EINA_INLIST_GET(map));
194 if (length) *length = map->size; 233 if (length) *length = map->size;
234 if (stride) *stride = dst_stride;
195 return map->ptr; 235 return map->ptr;
196 236
197on_fail: 237on_fail:
@@ -214,7 +254,41 @@ _ector_software_buffer_base_ector_generic_buffer_unmap(Eo *obj EINA_UNUSED, Ecto
214 { 254 {
215 pd->internal.maps = eina_inlist_remove(pd->internal.maps, EINA_INLIST_GET(map)); 255 pd->internal.maps = eina_inlist_remove(pd->internal.maps, EINA_INLIST_GET(map));
216 if (map->allocated) 256 if (map->allocated)
217 free(map->ptr); 257 {
258 if (map->mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE)
259 {
260 unsigned k, dst_stride;
261
262 if (map->cspace != pd->generic->cspace)
263 {
264 if (pd->generic->cspace == EFL_GFX_COLORSPACE_ARGB8888)
265 {
266 for (k = 0; k < map->h; k++)
267 _pixels_gry8_to_argb_convert((uint32_t *) (pd->pixels.u8 + (k + map->y) * pd->stride),
268 map->ptr + (k * map->w),
269 map->w);
270 }
271 else
272 {
273 for (k = 0; k < map->h; k++)
274 _pixels_argb_to_gry8_convert(pd->pixels.u8 + (k + map->y) * pd->stride,
275 (uint32_t *) map->ptr + (k * map->w),
276 map->w);
277 }
278 }
279 else
280 {
281 dst_stride = _min_stride_calc(map->w, map->cspace);
282 for (k = 0; k < map->h; k++)
283 {
284 memcpy(pd->pixels.u8 + map->x + (k + map->y) * pd->stride,
285 map->ptr + k * dst_stride,
286 dst_stride);
287 }
288 }
289 }
290 free(map->ptr);
291 }
218 free(map); 292 free(map);
219 return; 293 return;
220 } 294 }