1 /* x86_convert.c - convert RImage to XImage with x86 optimizations
3 * Raster graphics library
5 * Copyright (c) 2000 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 static int result
= -1;
42 ("pushfl \n" // check whether cpuid supported
44 "movl %%eax, %%ebx \n"
45 "xorl 1<<21, %%eax \n"
50 "xorl %%eax, %%ebx \n"
51 "andl 1<<21, %%eax \n"
53 "xorl %%eax, %%eax \n"
57 "test 1<<23, %%edx \n"
73 * 32/8 24/8 32/16 24/16 32/24 24/24
83 x86_mmx_TrueColor_32_to_16(unsigned char *image
, // 8
84 unsigned short *ximage
, // 12
93 unsigned int roffs
, // 48
94 unsigned int goffs
, // 52
95 unsigned int boffs
, // 56
98 int line_offset
) // 68
102 long long rrggbbaa;// -16
103 long long pixel; //-24
104 short *tmp_err; //-32
105 short *tmp_nerr; //-36
110 "andl $-8, %ebp \n" // make it align
111 "subl $128, %esp \n" // alloc some more stack
115 // pack dr, dg and db into mm6
116 "movl 36(%ebp), %eax \n"
117 "movl 40(%ebp), %ebx \n"
118 "movw %ax, -16(%ebp) \n"
120 "movw %bx, -14(%ebp) \n"
121 "movl 44(%ebp), %eax \n"
122 "movw $0, -10(%ebp) \n"
123 "movw %ax, -12(%ebp) \n"
125 "movq -16(%ebp), %mm6 \n" // dr dg db 0
127 // pack 4|4|4|4 into mm7, for shifting (/16)
128 "movl $0x00040004, -16(%ebp) \n"
129 "movl $0x00040004, -12(%ebp) \n"
130 "movq -16(%ebp), %mm7 \n"
132 // store constant values for using with mmx when dithering
133 "movl $0x00070007, -16(%ebp) \n"
134 "movl $0x00070007, -12(%ebp) \n"
135 "movq -16(%ebp), %mm5 \n"
137 "movl $0x00050005, -16(%ebp) \n"
138 "movl $0x00050005, -12(%ebp) \n"
139 "movq -16(%ebp), %mm4 \n"
141 "movl $0x00030003, -16(%ebp) \n"
142 "movl $0x00030003, -12(%ebp) \n"
143 "movq -16(%ebp), %mm3 \n"
145 // process 1 pixel / cycle, each component treated as 16bit
146 "movl 8(%ebp), %esi \n" // esi = image->data
149 "movl 60(%ebp), %eax \n"
150 "movl %eax, -4(%ebp) \n" // x = width
152 "movl 64(%ebp), %eax \n"
153 "decl %eax \n" // y--
154 "movl %eax, 64(%ebp) \n"
155 "js .Enda \n" // if y < 0, goto end
157 "jz .LoopY_1a \n" // if (y&1) goto LoopY_1
161 "movl 16(%ebp), %ebx \n" // ebx = err
162 "movl %ebx, -36(%ebp) \n" // [-36] = err
163 "movl 20(%ebp), %eax \n" //
164 "movl %eax, -32(%ebp) \n" // [-32] = nerr
170 "movl 20(%ebp), %ebx \n" // ebx = nerr
171 "movl %ebx, -36(%ebp) \n" // [-36] = nerr
172 "movl 16(%ebp), %eax \n" //
173 "movl %eax, -32(%ebp) \n" // [-32] = eerr
178 // calculate errors and pixel components
180 // depend on ebx, esi, mm6
181 "movq (%ebx), %mm1 \n" // mm1 = error[0..3]
182 "punpcklbw (%esi), %mm0 \n" // mm0 = image->data[0..3]
183 "psrlw $8, %mm0 \n" // fixup mm0
184 "paddusb %mm1, %mm0 \n" // mm0 = mm0 + mm1 (sat. to 255)
185 "movq %mm0, -24(%ebp) \n" // save the pixel
187 "movzwl -24(%ebp), %ecx \n" // ecx = pixel.red
188 "movl 24(%ebp), %edi \n" // edi = rtable
189 "leal (%edi, %ecx, 2), %eax \n" // eax = &rtable[pixel.red]
190 "movl (%eax), %edx \n" // edx = rtable[pixel.red]
191 "movw %dx, -16(%ebp) \n" // save rr
193 "movzwl -22(%ebp), %ecx \n" // ecx = pixel.green
194 "movl 28(%ebp), %edi \n" // edi = gtable
195 "leal (%edi, %ecx, 2), %eax \n" // eax = >able[pixel.green]
196 "movl (%eax), %edx \n" // ebx = gtable[pixel.green]
197 "movw %dx, -14(%ebp) \n" // save gg
199 "movzwl -20(%ebp), %ecx \n" // ecx = pixel.blue
200 "movl 32(%ebp), %edi \n" // ebx = btable
201 "leal (%edi, %ecx, 2), %eax \n" // eax = &btable[pixel.blue]
202 "movl (%eax), %edx \n" // ecx = btable[pixel.blue]
203 "movw %dx, -12(%ebp) \n" // save bb
205 "movw $0, -10(%ebp) \n" // save dummy aa
207 "movq -16(%ebp), %mm1 \n" // load mm1 with rrggbbaa
208 "pmullw %mm6, %mm1 \n" // mm1 = rr*dr|...
209 "psubsw %mm1, %mm0 \n" // error = pixel - mm1
212 // distribute the error
214 // depend on mm0, mm7, mm3, mm4, mm5
216 "movl -36(%ebp), %ebx \n"
219 "pmullw %mm5, %mm1 \n" // mm1 = mm1*7
220 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16
221 "paddw 8(%ebx), %mm1 \n"
222 "movq %mm1, 8(%ebx) \n" // err[x+1,y] = rer*7/16
225 "movl -32(%ebp), %ebx \n"
228 "pmullw %mm4, %mm1 \n" // mm1 = mm1*5
229 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16
230 "paddw -8(%ebx), %mm1 \n"
231 "movq %mm1, -8(%ebx) \n" // err[x-1,y+1] += rer*3/16
234 "pmullw %mm3, %mm1 \n" // mm1 = mm1*3
235 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16
236 "paddw 8(%ebx), %mm1 \n"
237 "movq %mm1, (%ebx) \n" // err[x,y+1] += rer*5/16
239 "psrlw %mm7, %mm0 \n" // mm0 = mm0/16
240 "movq %mm0, 8(%ebx) \n" // err[x+1,y+1] = rer/16
243 // calculate final pixel value and store
244 "movl 48(%ebp), %ecx \n"
245 "movw -16(%ebp), %ax \n"
246 "shlw %cl, %ax \n" //NP* ax = r<<roffs
248 "movl 52(%ebp), %ecx \n"
249 "movw -14(%ebp), %bx \n"
250 "shlw %cl, %bx \n" //NP*
253 "movl 56(%ebp), %ecx \n"
254 "movw -12(%ebp), %bx \n"
255 "shlw %cl, %bx \n" //NP*
258 "movl 12(%ebp), %edx \n"
259 "movw %ax, (%edx) \n"
260 "addl $2, %edx \n" // increment ximage
261 "movl %edx, 12(%ebp) \n"
263 // prepare for next iteration on X
265 "addl $8, -32(%ebp) \n" // nerr += 8
267 "movl -36(%ebp), %ebx \n"
269 "movl %ebx, -36(%ebp) \n" // ebx = err += 8
272 // Note: in the last pixel, this would cause an invalid memory access
273 // because, punpcklbw is used (which reads 8 bytes) and the last
274 // pixel is only 4 bytes. This is no problem because the image data
275 // was allocated with extra 4 bytes when created.
276 "addl $4, %esi \n" // image->data += 4
279 "decl -4(%ebp) \n" // x--
280 "jnz .LoopXa \n" // if x>0, goto .LoopX
284 "addl 68(%ebp), %edx \n" // add extra offset to ximage
285 "movl %edx, 12(%ebp) \n"
290 ".Enda: \n" // THE END
299 #endif /* ASM_X86_MMX */
303 /* convert and dither the image to XImage */
304 for (y
=0; y
<image
->height
; y
++) {
308 for (x
=0; x
<image
->width
*3; x
+=3, ptr
+=channels
) {
311 pixel
= *ptr
+ err
[x
];
312 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
318 pixel
= *(ptr
+1) + err
[x
+1];
319 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
325 pixel
= *(ptr
+2) + err
[x
+2];
326 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
331 *optr
++ = pixels
[r
*cpcpc
+ g
*cpc
+ b
];
333 /* distribute error */
347 nerr
[x
+1+3*1]=ger
-2*g
;
348 nerr
[x
+2+3*1]=ber
-2*b
;
350 /* skip to next line */
355 optr
+= ximg
->image
->bytes_per_line
- image
->width
;
362 x86_PseudoColor_32_to_8(unsigned char *image
, // 8
363 unsigned char *ximage
, // 12
372 unsigned long *pixels
, // 48
376 int line_offset
) // 64
381 "subl $128, %esp \n" // alloc some stack space
384 // process 1 pixel / cycle, each component treated as 16bit
385 "movl 8(%ebp), %esi \n" // esi = image->data
388 "movl 56(%ebp), %eax \n"
389 "movl %eax, -4(%ebp) \n" // x = width
391 "movl 60(%ebp), %eax \n"
392 "decl %eax \n" // y--
393 "movl %eax, 64(%ebp) \n"
394 "js .Endb \n" // if y < 0, goto end
396 "jz .LoopY_1b \n" // if (y&1) goto LoopY_1
400 "movl 16(%ebp), %ebx \n" // ebx = err
401 "movl %ebx, -36(%ebp) \n" // [-36] = err
402 "movl 20(%ebp), %eax \n" //
403 "movl %eax, -32(%ebp) \n" // [-32] = nerr
405 "movl $0, -32(%ebp) \n" // init error of nerr[0] to 0
411 "movl 20(%ebp), %ebx \n" // ebx = nerr
412 "movl %ebx, -36(%ebp) \n" // [-36] = nerr
413 "movl 16(%ebp), %eax \n" //
414 "movl %eax, -32(%ebp) \n" // [-32] = err
416 "movl $0, -32(%ebp) \n" // init error of nerr[0] to 0
420 "movl (%esi), %edx \n" // fetch a pixel