summaryrefslogtreecommitdiff
path: root/src/lib/ector/software/ector_software_buffer.c
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2015-11-18 19:29:23 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2015-12-03 18:42:50 +0900
commit0cf5719e526b17bb6ad03f05643a760edf389e98 (patch)
treeabe50314b8b47867fe21c69ca754486030d08d15 /src/lib/ector/software/ector_software_buffer.c
parentb41e66c1ef9928b506ed1f6e0ef9e033e25edf02 (diff)
Ector: Implement pixel buffer support
The objective of this patch is to propose a standardized format for pixel buffers to use within Ector and Evas. The basic EO API provided here is not meant to be the fastest path for all operations, simply the most convenient to generalize. Performance will be achieved by implementing (or porting) custom draw functions. This implements support for: - Generic pixel buffers - Generic buffer renderer to draw images with ector - Software engine pixel buffers, ie. malloc buffers - Software buffer renderer Cairo support has not been implemented yet. The only renderer is still extremely limited, as it does not support Fill modes, Scaling, etc... yet. Not a single line from this patch has been tested yet. It compiles. That's pretty damn good for a start! @feature
Diffstat (limited to 'src/lib/ector/software/ector_software_buffer.c')
-rw-r--r--src/lib/ector/software/ector_software_buffer.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/src/lib/ector/software/ector_software_buffer.c b/src/lib/ector/software/ector_software_buffer.c
new file mode 100644
index 0000000000..4fdbcde947
--- /dev/null
+++ b/src/lib/ector/software/ector_software_buffer.c
@@ -0,0 +1,248 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#else
4# define EFL_BETA_API_SUPPORT
5#endif
6
7#include <Eo.h>
8#include "Ector_Software.h"
9#include "ector_private.h"
10#include "ector_software_private.h"
11#include "ector_generic_buffer.eo.h"
12
13#define fail(fmt, ...) do { ERR(fmt, ##__VA_ARGS__); goto on_fail; } while (0)
14
15static inline int
16_min_stride_calc(int width, Efl_Gfx_Colorspace cspace)
17{
18 switch (cspace)
19 {
20 case EFL_GFX_COLORSPACE_ARGB8888: return width * 4;
21 case EFL_GFX_COLORSPACE_GRY8: return width;
22 default: return 0;
23 }
24}
25
26/* FIXME: Conversion routines don't belong here */
27static inline void
28_pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len)
29{
30 int k;
31 for (k = 0; k < len; k++)
32 {
33 const uint32_t *s = src++;
34 *dst++ = A_VAL(s);
35 }
36}
37
38static inline void
39_pixels_gry8_to_argb_convert(uint32_t *dst, const uint8_t *src, int len)
40{
41 int k;
42 for (k = 0; k < len; k++)
43 {
44 uint8_t s = *src++;
45 *dst++ = ARGB_JOIN(s, s, s, s);
46 }
47}
48
49EOLIAN static void
50_ector_software_buffer_pixels_clear(Eo *obj, Ector_Software_Buffer_Data *pd)
51{
52 if (!pd->pixels.u8)
53 return;
54
55 eo_do(obj, eo_event_callback_call(ECTOR_GENERIC_BUFFER_EVENT_DETACHED, pd->pixels.u8));
56 if (!pd->nofree)
57 {
58 free(pd->pixels.u8);
59 }
60 pd->pixels.u8 = NULL;
61 pd->nofree = EINA_FALSE;
62}
63
64EOLIAN static Eina_Bool
65_ector_software_buffer_ector_generic_buffer_pixels_set(Eo *obj, Ector_Software_Buffer_Data *pd,
66 void *pixels, int width, int height, int stride,
67 Efl_Gfx_Colorspace cspace, Eina_Bool writable,
68 unsigned char l, unsigned char r,
69 unsigned char t, unsigned char b)
70{
71 // safety check
72 unsigned px = _min_stride_calc(1, cspace);
73 if (px && ((unsigned long long)(uintptr_t)pixels) & (px - 1))
74 ERR("Pixel data is not aligned to %u bytes!", px);
75
76 if ((cspace != EFL_GFX_COLORSPACE_ARGB8888) &&
77 (cspace != EFL_GFX_COLORSPACE_GRY8))
78 {
79 ERR("Unsupported colorspace: %u", cspace);
80 return EINA_FALSE;
81 }
82
83 if (!stride)
84 stride = _min_stride_calc(width + l + r, cspace);
85 else if (stride < _min_stride_calc(width + l + r, cspace))
86 {
87 ERR("Invalid stride %u for width %u (+%u+%u) cspace %u. pixels_set failed.",
88 stride, width, l, r, cspace);
89 _ector_software_buffer_pixels_clear(obj, pd);
90 return EINA_FALSE;
91 }
92
93 if (pd->pixels.u8 && (pd->pixels.u8 != pixels))
94 _ector_software_buffer_pixels_clear(obj, pd);
95
96 if (pixels)
97 {
98 pd->pixels.u8 = pixels;
99 pd->nofree = EINA_TRUE;
100 pd->writable = !!writable;
101 }
102 else
103 {
104 pd->pixels.u8 = malloc(stride * (height + t + b));
105 pd->nofree = EINA_FALSE;
106 pd->writable = EINA_TRUE;
107 }
108 pd->generic.w = width;
109 pd->generic.h = height;
110 pd->generic.l = l;
111 pd->generic.r = r;
112 pd->generic.t = t;
113 pd->generic.b = b;
114 pd->generic.cspace = cspace;
115 pd->stride = stride;
116 return EINA_TRUE;
117}
118
119EOLIAN static uint8_t *
120_ector_software_buffer_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_Software_Buffer_Data *pd,
121 int *offset, unsigned int *length,
122 Ector_Buffer_Access_Flag mode EINA_UNUSED,
123 unsigned int x, unsigned int y, unsigned int w, unsigned int h,
124 Efl_Gfx_Colorspace cspace EINA_UNUSED, unsigned int *stride)
125{
126 int off;
127
128 if (!pd->pixels.u8 || !pd->stride)
129 fail("Buffer has no pixel data yet");
130 if (cspace != pd->generic.cspace)
131 fail("Invalid colorspace");
132 if (!w || !h || ((x + w) > pd->generic.w) || (y + h > pd->generic.h))
133 fail("Invalid region requested: wanted %u,%u %ux%u but image is %ux%u",
134 x, y, w, h, pd->generic.w, pd->generic.h);
135
136 pd->map_count++;
137 off = _min_stride_calc(x + pd->generic.l, pd->generic.cspace) + (pd->stride * (y + pd->generic.t));
138 if (offset) *offset = off;
139 if (length) *length = (pd->stride * pd->generic.h) - off;
140 if (stride) *stride = pd->stride;
141 return pd->pixels.u8;
142
143on_fail:
144 if (offset) *offset = 0;
145 if (length) *length = 0;
146 if (stride) *stride = 0;
147 return NULL;
148}
149
150EOLIAN static void
151_ector_software_buffer_ector_generic_buffer_unmap(Eo *obj EINA_UNUSED, Ector_Software_Buffer_Data *pd, void *data, int offset EINA_UNUSED, unsigned int length EINA_UNUSED)
152{
153 if (!data) return;
154 if (data != pd->pixels.u8)
155 {
156 CRI("Trying to unmap a non-mapped region!");
157 return;
158 }
159 if (pd->map_count == 0)
160 {
161 CRI("Unmapped too many times! Check your code!");
162 return;
163 }
164 pd->map_count--;
165}
166
167EOLIAN uint8_t *
168_ector_software_buffer_ector_generic_buffer_span_get(Eo *obj EINA_UNUSED, Ector_Software_Buffer_Data *pd,
169 int x, int y, unsigned int w, Efl_Gfx_Colorspace cspace,
170 unsigned int *length)
171{
172 uint8_t *src;
173 int len, px;
174
175 if (!pd->pixels.u8)
176 fail("No pixel data");
177 if ((x < -pd->generic.l) || (y < -pd->generic.t) ||
178 ((unsigned) x > pd->generic.w) || ((unsigned) y > pd->generic.h))
179 fail("Out of bounds");
180 if (((unsigned) x + w) > (pd->generic.w + pd->generic.l + pd->generic.r))
181 fail("Requested span too large");
182
183 px = _min_stride_calc(1, pd->generic.cspace);
184 len = _min_stride_calc(w, cspace);
185 if (length) *length = len;
186
187 src = pd->pixels.u8 + ((pd->generic.t + y) * pd->stride) + (px * (pd->generic.l + x));
188
189 if (cspace == pd->generic.cspace)
190 {
191 pd->span_free = EINA_FALSE;
192 return src;
193 }
194 else if ((cspace == EFL_GFX_COLORSPACE_ARGB8888) &&
195 (pd->generic.cspace == EFL_GFX_COLORSPACE_GRY8))
196 {
197 uint32_t *buf = malloc(len);
198 _pixels_gry8_to_argb_convert(buf, src, w);
199 pd->span_free = EINA_TRUE;
200 return (uint8_t *) buf;
201 }
202 else if ((cspace == EFL_GFX_COLORSPACE_GRY8) &&
203 (pd->generic.cspace == EFL_GFX_COLORSPACE_ARGB8888))
204 {
205 uint8_t *buf = malloc(len);
206 _pixels_argb_to_gry8_convert(buf, (uint32_t *) src, w);
207 pd->span_free = EINA_TRUE;
208 return buf;
209 }
210 else
211 fail("Unsupported colorspace %u", cspace);
212
213on_fail:
214 if (length) *length = 0;
215 return NULL;
216}
217
218EOLIAN void
219_ector_software_buffer_ector_generic_buffer_span_free(Eo *obj EINA_UNUSED, Ector_Software_Buffer_Data *pd,
220 uint8_t *data)
221{
222 if (pd->span_free) free(data);
223 pd->span_free = EINA_FALSE;
224}
225
226EOLIAN static Ector_Buffer_Flag
227_ector_software_buffer_ector_generic_buffer_flags_get(Eo *obj EINA_UNUSED, Ector_Software_Buffer_Data *pd)
228{
229 return ECTOR_BUFFER_FLAG_CPU_READABLE |
230 ECTOR_BUFFER_FLAG_CPU_READABLE_FAST |
231 ECTOR_BUFFER_FLAG_RENDERABLE |
232 (pd->writable ? (ECTOR_BUFFER_FLAG_CPU_WRITABLE |
233 ECTOR_BUFFER_FLAG_CPU_WRITABLE_FAST)
234 : 0);
235}
236
237EOLIAN static void
238_ector_software_buffer_eo_base_destructor(Eo *obj, Ector_Software_Buffer_Data *pd)
239{
240 _ector_software_buffer_pixels_clear(obj, pd);
241 eo_do_super(obj, ECTOR_SOFTWARE_BUFFER_CLASS, eo_destructor());
242 if (pd->map_count)
243 {
244 ERR("Pixel data is still mapped during destroy! Check your code!");
245 }
246}
247
248#include "ector_software_buffer.eo.c"