1 /*
2 Format conversion handle routines for the HERMES library
3 Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk)
4 This source code is licensed under the GNU LGPL
5
6 Please refer to the file COPYING.LIB contained in the distribution for
7 licensing conditions
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "H_Conv.h"
14 #include "H_Format.h"
15 #include "H_Pal.h"
16 #include "H_Blit.h"
17 #include "Palette.h"
18 #include "Factory.h"
19 #include "Convert.h"
20 #include "HermConf.h"
21 #include "HeadC.h"
22 #include "HeadX86.h"
23 #include "HeadMMX.h"
24 #include "Debug.h"
25
26 /* ConverterList is a list of HermesConverter* */
27
28 /* This static array is used by programs that require less than (HERMES_INITIAL) number of handles */
29 /* (Usually programs only require one handle - the static array is used to prevent unnecessary malloc's) */
30 /* If a larger array is required - A new memory block will be allocated */
31 static HermesConverter *StaticConverterList[HERMES_INITIAL];
32
33 static HermesConverter **ConverterList = 0; // Points to the converter memory (0 = not initialised)
34 static int LastConverter; // Array size
35 static int NextHandle; // The next handle that is possible free (used to optimise searching)
36 static int RefCount; // Contains the number of used handles
37
38 HermesJumpTable HJT_NONE[4] = {
39 {0, 0, "Not Available" },
40 {0, 0, "Not Available" },
41 {0, 0, "Not Available" },
42 {0, 0, "Not Available" }
43 };
44
45 static HermesJumpTable Blit_HJT_CC_32[4] = {
46 {ConvertC_Generic32_C_Generic8_C_Blit, ConvertC_Generic32_C_Generic8_C_S_Blit, "Generic32_C_Generic8_C" },
47 {ConvertC_Generic32_C_Generic16_C_Blit, ConvertC_Generic32_C_Generic16_C_S_Blit, "Generic32_C_Generic16_C" },
48 {ConvertC_Generic32_C_Generic24_C_Blit, ConvertC_Generic32_C_Generic24_C_S_Blit, "Generic32_C_Generic24_C" },
49 {ConvertC_Generic32_C_Generic32_C_Blit, ConvertC_Generic32_C_Generic32_C_S_Blit, "Generic32_C_Generic32_C" }
50 };
51
52 static HermesJumpTable Blit_HJT_CC_24[4] = {
53 {ConvertC_Generic24_C_Generic8_C_Blit, ConvertC_Generic24_C_Generic8_C_S_Blit, "Generic24_C_Generic8_C" },
54 {ConvertC_Generic24_C_Generic16_C_Blit, ConvertC_Generic24_C_Generic16_C_S_Blit, "Generic24_C_Generic16_C" },
55 {ConvertC_Generic24_C_Generic24_C_Blit, ConvertC_Generic24_C_Generic24_C_S_Blit, "Generic24_C_Generic24_C" },
56 {ConvertC_Generic24_C_Generic32_C_Blit, ConvertC_Generic24_C_Generic32_C_S_Blit, "Generic24_C_Generic32_C" }
57 };
58
59 static HermesJumpTable Blit_HJT_CC_16[4] = {
60 {ConvertC_Generic16_C_Generic8_C_Blit, ConvertC_Generic16_C_Generic8_C_S_Blit, "Generic16_C_Generic8_C" },
61 {ConvertC_Generic16_C_Generic16_C_Blit, ConvertC_Generic16_C_Generic16_C_S_Blit, "Generic16_C_Generic16_C" },
62 {ConvertC_Generic16_C_Generic24_C_Blit, ConvertC_Generic16_C_Generic24_C_S_Blit, "Generic16_C_Generic24_C" },
63 {ConvertC_Generic16_C_Generic32_C_Blit, ConvertC_Generic16_C_Generic32_C_S_Blit, "Generic16_C_Generic32_C" }
64 };
65
66
67 static HermesJumpTable Blit_HJT_AO_32[4] = {
68 {ConvertC_Generic32_A_Generic8_O_Blit, ConvertC_Generic32_A_Generic8_O_S_Blit, "Generic32_A_Generic8_O" },
69 {ConvertC_Generic32_A_Generic16_O_Blit, ConvertC_Generic32_A_Generic16_O_S_Blit, "Generic32_A_Generic16_O" },
70 {ConvertC_Generic32_A_Generic24_O_Blit, ConvertC_Generic32_A_Generic24_O_S_Blit, "Generic32_A_Generic24_O" },
71 {ConvertC_Generic32_A_Generic32_O_Blit, ConvertC_Generic32_A_Generic32_O_S_Blit, "Generic32_A_Generic32_O" }
72 };
73
74 static HermesJumpTable Blit_HJT_AO_24[4] = {
75 {ConvertC_Generic24_A_Generic8_O_Blit, ConvertC_Generic24_A_Generic8_O_S_Blit, "Generic24_A_Generic8_O" },
76 {ConvertC_Generic24_A_Generic16_O_Blit, ConvertC_Generic24_A_Generic16_O_S_Blit, "Generic24_A_Generic16_O" },
77 {ConvertC_Generic24_A_Generic24_O_Blit, ConvertC_Generic24_A_Generic24_O_S_Blit, "Generic24_A_Generic24_O" },
78 {ConvertC_Generic24_A_Generic32_O_Blit, ConvertC_Generic24_A_Generic32_O_S_Blit, "Generic24_A_Generic32_O" }
79 };
80
81 static HermesJumpTable Blit_HJT_AO_16[4] = {
82 {ConvertC_Generic16_A_Generic8_O_Blit, ConvertC_Generic16_A_Generic8_O_S_Blit, "Generic16_A_Generic8_O" },
83 {ConvertC_Generic16_A_Generic16_O_Blit, ConvertC_Generic16_A_Generic16_O_S_Blit, "Generic16_A_Generic16_O" },
84 {ConvertC_Generic16_A_Generic24_O_Blit, ConvertC_Generic16_A_Generic24_O_S_Blit, "Generic16_A_Generic24_O" },
85 {ConvertC_Generic16_A_Generic32_O_Blit, ConvertC_Generic16_A_Generic32_O_S_Blit, "Generic16_A_Generic32_O" }
86 };
87
88 static HermesJumpTable Blit_HJT_CO_32[4] = {
89 {ConvertC_Generic32_C_Generic8_O_Blit, ConvertC_Generic32_C_Generic8_O_S_Blit, "Generic32_C_Generic8_O" },
90 {ConvertC_Generic32_C_Generic16_O_Blit, ConvertC_Generic32_C_Generic16_O_S_Blit, "Generic32_C_Generic16_O" },
91 {ConvertC_Generic32_C_Generic24_O_Blit, ConvertC_Generic32_C_Generic24_O_S_Blit, "Generic32_C_Generic24_O" },
92 {ConvertC_Generic32_C_Generic32_O_Blit, ConvertC_Generic32_C_Generic32_O_S_Blit, "Generic32_C_Generic32_O" }
93 };
94
95 static HermesJumpTable Blit_HJT_CO_24[4] = {
96 {ConvertC_Generic24_C_Generic8_O_Blit, ConvertC_Generic24_C_Generic8_O_S_Blit, "Generic24_C_Generic8_O" },
97 {ConvertC_Generic24_C_Generic16_O_Blit, ConvertC_Generic24_C_Generic16_O_S_Blit, "Generic24_C_Generic16_O" },
98 {ConvertC_Generic24_C_Generic24_O_Blit, ConvertC_Generic24_C_Generic24_O_S_Blit, "Generic24_C_Generic24_O" },
99 {ConvertC_Generic24_C_Generic32_O_Blit, ConvertC_Generic24_C_Generic32_O_S_Blit, "Generic24_C_Generic32_O" }
100 };
101
102 static HermesJumpTable Blit_HJT_CO_16[4] = {
103 {ConvertC_Generic16_C_Generic8_O_Blit, ConvertC_Generic16_C_Generic8_O_S_Blit, "Generic16_C_Generic8_O" },
104 {ConvertC_Generic16_C_Generic16_O_Blit, ConvertC_Generic16_C_Generic16_O_S_Blit, "Generic16_C_Generic16_O" },
105 {ConvertC_Generic16_C_Generic24_O_Blit, ConvertC_Generic16_C_Generic24_O_S_Blit, "Generic16_C_Generic24_O" },
106 {ConvertC_Generic16_C_Generic32_O_Blit, ConvertC_Generic16_C_Generic32_O_S_Blit, "Generic16_C_Generic32_O" }
107 };
108
109 static HermesJumpTable Blit_HJT_CopyOnly_32[4] = {
110 {ConvertC_Generic32_Generic8, ConvertC_Generic32_Generic8_S, "Generic32_Generic8" },
111 {ConvertC_Generic32_Generic16, ConvertC_Generic32_Generic16_S, "Generic32_Generic16" },
112 {ConvertC_Generic32_Generic24, ConvertC_Generic32_Generic24_S, "Generic32_Generic24" },
113 {ConvertC_Generic32_Generic32, ConvertC_Generic32_Generic32_S, "Generic32_Generic32" }
114 };
115
116 static HermesJumpTable Blit_HJT_CopyOnly_24[4] = {
117 {ConvertC_Generic24_Generic8, ConvertC_Generic24_Generic8_S, "Generic24_Generic8" },
118 {ConvertC_Generic24_Generic16, ConvertC_Generic24_Generic16_S, "Generic24_Generic16" },
119 {ConvertC_Generic24_Generic24, ConvertC_Generic24_Generic24_S, "Generic24_Generic24" },
120 {ConvertC_Generic24_Generic32, ConvertC_Generic24_Generic32_S, "Generic24_Generic32" }
121 };
122
123 static HermesJumpTable Blit_HJT_CopyOnly_16[4] = {
124 {ConvertC_Generic16_Generic8, ConvertC_Generic16_Generic8_S, "Generic16_Generic8" },
125 {ConvertC_Generic16_Generic16, ConvertC_Generic16_Generic16_S, "Generic16_Generic16" },
126 {ConvertC_Generic16_Generic24, ConvertC_Generic16_Generic24_S, "Generic16_Generic24" },
127 {ConvertC_Generic16_Generic32, ConvertC_Generic16_Generic32_S, "Generic16_Generic32" }
128 };
129 static HermesJumpTable *Blit_HJT_CC[4] = { HJT_NONE, Blit_HJT_CC_16, Blit_HJT_CC_24, Blit_HJT_CC_32 };
130 static HermesJumpTable *Blit_HJT_AO[4] = { HJT_NONE, Blit_HJT_AO_16, Blit_HJT_AO_24, Blit_HJT_AO_32 };
131 static HermesJumpTable *Blit_HJT_CO[4] = { HJT_NONE, Blit_HJT_CO_16, Blit_HJT_CO_24, Blit_HJT_CO_32 };
132 static HermesJumpTable *Blit_HJT_CopyOnly[4] = { HJT_NONE, Blit_HJT_CopyOnly_16, Blit_HJT_CopyOnly_24, Blit_HJT_CopyOnly_32 };
133
134 // *** This table is as of Hermes 1.3.2 - It looks incorrect ***
135 static HermesJumpTableList Blit_HJT = {
136 Blit_HJT_CC, NULL, NULL, Blit_HJT_AO, Blit_HJT_AO, Blit_HJT_CO, Blit_HJT_CopyOnly };
137
Hermes_BlitterInstance(unsigned long flags)138 HermesHandle HERMES_API Hermes_BlitterInstance(unsigned long flags)
139 {
140 int i;
141 HermesConverter *newinstance;
142 HermesConverter **newlist;
143 HermesConverter **cptr;
144 int cptr_id;
145 int new_size;
146
147 DEBUG_PRINT("Hermes_BlitterInstance called\n","");
148 /* Initialising, allocate initial size array of converters */
149
150 if (!ConverterList) { // ConverterList not initialised. (Called on the first call to this function)
151 memset(StaticConverterList, 0, sizeof(StaticConverterList)); // Clear the array
152 ConverterList = StaticConverterList; // Set the ConverterList address to the static array
153 LastConverter=HERMES_INITIAL; // Size of the StaticConvertList array
154 NextHandle=1; // Set the handle will be free
155 RefCount=0; // Number of used handles
156 }
157
158 cptr = 0; // Flag the converter pointer has not been found
159 cptr_id = 0;
160
161 // If the next handle is free use it now (to prevent unnecessary searching)
162 if (NextHandle < LastConverter) // Valid next handle
163 {
164 if (!ConverterList[NextHandle]) // Found a free handle
165 {
166 cptr = &(ConverterList[NextHandle]); // The free handle
167 cptr_id = NextHandle; // The handle id
168 }
169 }
170
171 if (!cptr) // handle not found - do a full search
172 {
173 // Note, I start searching at one (not zero) this is intentional - since returning zero also denotes an error
174 for (i=1; i<LastConverter; i++) // For all the converters
175 {
176 if (!ConverterList[i]) // Found an empty slot
177 {
178 cptr = &(ConverterList[i]); // The free handle
179 cptr_id = i; // The handle id
180 break;
181 }
182 }
183 }
184
185 if (!cptr) // No free slot found
186 {
187
188 /* Uh oh, arrary too small, time for growth */
189 new_size = LastConverter+HERMES_GROWTH;
190 newlist=(HermesConverter **)malloc(sizeof(HermesConverter*) * new_size);
191 if (!newlist) return 0;
192
193 /* Copy converter pointers */
194
195 for (i=0;i<LastConverter;i++) // Copy each existing converters
196 {
197 newlist[i]=ConverterList[i];
198 }
199 for ( ; i < new_size; i++ ) // Clear the new elements of the array
200 {
201 newlist[i]=0;
202 }
203
204 if (ConverterList != StaticConverterList) // Do not deallocate the static array
205 {
206 free(ConverterList);
207 }
208
209 /* Assign new list to old one */
210 ConverterList=newlist;
211
212 cptr = &(ConverterList[LastConverter]); // The free handle
213 cptr_id = LastConverter; // The handle id
214
215 LastConverter = new_size;
216
217 DEBUG_PRINT("Growing dynamic array, new size %d\n",LastConverter)
218 }
219
220 /* Create a HermesConverter */
221
222 /* Note: allocates and clears the list */
223 newinstance=(HermesConverter *)calloc(1, sizeof(HermesConverter));
224 if (!newinstance) return 0;
225 newinstance->flags=flags;
226
227 RefCount++;
228
229 *cptr = newinstance; // Store the new HermesConverter
230 NextHandle = cptr_id + 1; // Set the next possible free handle
231 return cptr_id;
232 }
233
234
235
Hermes_BlitterReturn(HermesHandle handle)236 void HERMES_API Hermes_BlitterReturn(HermesHandle handle)
237 {
238 if (!ConverterList) return; // Return called before Init
239 if (handle<=0 || handle>=LastConverter) return; // Invalid handle
240 if (!ConverterList[handle]) return; // Already deallocated
241
242 free(ConverterList[handle]); // Free the handle
243 ConverterList[handle]=0; // Flag handle freed
244
245 NextHandle = handle; // Flag where the free handle is located
246
247 RefCount--;
248 /* No more references, deinitialise */
249 if (!RefCount)
250 {
251 if (ConverterList != StaticConverterList) // Not using the static array
252 {
253 free(ConverterList); // Free the array
254 ConverterList = StaticConverterList; // Set the ConverterList address to the static array
255 LastConverter=HERMES_INITIAL; // Size of the StaticConvertList array
256 }
257 NextHandle = 1; // Where the free handle is located
258 }
259 }
260
Hermes_BlitterRequest(HermesHandle handle,HermesFormat * source,HermesFormat * dest)261 int HERMES_API Hermes_BlitterRequest(HermesHandle handle, HermesFormat *source, HermesFormat *dest)
262 {
263 // Note - Not using specialised converters as we are blitting
264 return (Hermes_BlitterRequest_V2(handle, source, dest, 0, &Blit_HJT));
265 }
266
267 // api_flags : 0 = Do not look for the specialised converters
Hermes_BlitterRequest_V2(HermesHandle handle,HermesFormat * source,HermesFormat * dest,int api_flags,HermesJumpTableList * tptr)268 int HERMES_API Hermes_BlitterRequest_V2(HermesHandle handle, HermesFormat *source, HermesFormat *dest, int api_flags, HermesJumpTableList *tptr)
269 {
270 int searchlist;
271 int i;
272 HermesConverter *cnv;
273 int src_bits;
274 int dest_bits;
275 HermesJumpTable *jptr;
276
277 DEBUG_PRINT("Blitter Request\n","");
278 /* Check array ranges */
279
280 if (handle<0 || handle>=LastConverter) return 0;
281 if (!ConverterList[handle]) return 0;
282
283 cnv=ConverterList[handle];
284
285 /* Cache repeated requests of the same conversion */
286
287 if (Hermes_FormatEquals(source,&ConverterList[handle]->source) &&
288 Hermes_FormatEquals(dest,&ConverterList[handle]->dest))
289 {
290 DEBUG_PRINT("Cached converter, from bpp %d\n", source->bits);
291 DEBUG_PRINT("To bpp: %d\n", dest->bits);
292 DEBUG_PRINT("\tColorkey source: %d,\n", source->has_colorkey);
293 DEBUG_PRINT("\tColorkey dest: %d,\n", dest->has_colorkey);
294 return 1;
295 }
296
297 DEBUG_PRINT("\tColorkey source: %d,\n", source->has_colorkey);
298 DEBUG_PRINT("\tColorkey dest: %d,\n", dest->has_colorkey);
299
300 DEBUG_PRINT("source ->a: %x,\n", (int) source->a);
301 DEBUG_PRINT("dest ->a: %x,\n", (int) dest->a);
302
303 /* Clear the generic converter flag */
304
305 cnv->flags&=~HERMES_CONVERT_GENERIC;
306
307 /* If the source and destination are equal and src no alph, use copy routines */
308
309 if (Hermes_FormatEquals(source,dest) && !source->a) {
310 DEBUG_PRINT("Source, dest equal! bpp %d\n", source->bits);
311 if ((source->bits&0x7)!=0 || source->bits > 32 || !source->bits) return 0;
312
313 i=(source->bits>>3)-1;
314
315 if (!equalConverters[i]) return 0;
316
317 Hermes_FormatCopy(source,&cnv->source);
318 Hermes_FormatCopy(dest,&cnv->dest);
319
320 cnv->loopnormal=equalConverters[i]->loopnormal;
321 cnv->loopstretch=equalConverters[i]->loopstretch;
322 cnv->normal=equalConverters[i]->normal;
323 cnv->stretch=equalConverters[i]->stretch;
324
325 return 1;
326 }
327
328 if (api_flags) /* Start looking for specialised converters */
329 {
330 searchlist=0xff;
331
332 switch (source->bits) {
333 case 32: if (source->r==0xff0000 && source->g==0xff00 && source->b==0xff)
334 searchlist=0;
335 else
336 if (source->r==0xff<<20 && source->g==0xff<<10 && source->b==0xff)
337 searchlist=3;
338 break;
339
340 case 24: if (source->r==0xff0000 && source->g==0xff00 && source->b==0xff)
341 searchlist=1; break;
342
343 case 16: if (source->r==0xf800 && source->g==0x7e0 && source->b==0x1f)
344 searchlist=2;
345 break;
346
347 case 8: if (source->indexed)
348 searchlist=4;
349 break;
350 }
351
352
353 /* We can use a quicker loop for 8 bit */
354
355 if (searchlist!=0xff)
356 if (source->bits==8) {
357 for (i=0;i<numConverters[searchlist];i++) {
358 if (standardConverters[searchlist][i])
359 if (dest->bits==standardConverters[searchlist][i]->dest.bits)
360 {
361 Hermes_FormatCopy(source,&cnv->source);
362 Hermes_FormatCopy(dest,&cnv->dest);
363
364 cnv->loopnormal=standardConverters[searchlist][i]->loopnormal;
365 cnv->loopstretch=standardConverters[searchlist][i]->loopstretch;
366
367 cnv->normal=standardConverters[searchlist][i]->normal;
368 cnv->stretch=standardConverters[searchlist][i]->stretch;
369
370 cnv->dither=standardConverters[searchlist][i]->dither;
371 cnv->ditherstretch=standardConverters[searchlist][i]->ditherstretch;
372
373 return 1;
374 }
375 }
376 }
377 else
378 for (i=0;i<numConverters[searchlist];i++) {
379 if (standardConverters[searchlist][i])
380 if (Hermes_FormatEquals(&standardConverters[searchlist][i]->source,source)&&
381 Hermes_FormatEquals(&standardConverters[searchlist][i]->dest,dest))
382 { Hermes_FormatCopy(source,&cnv->source);
383 Hermes_FormatCopy(dest,&cnv->dest);
384
385 cnv->loopnormal=standardConverters[searchlist][i]->loopnormal;
386 cnv->loopstretch=standardConverters[searchlist][i]->loopstretch;
387
388 cnv->normal=standardConverters[searchlist][i]->normal;
389 cnv->stretch=standardConverters[searchlist][i]->stretch;
390
391 cnv->dither=standardConverters[searchlist][i]->dither;
392 cnv->ditherstretch=standardConverters[searchlist][i]->ditherstretch;
393
394 return 1;
395 }
396 }
397 }
398
399 /* Find a generic converter */
400
401 cnv->loopnormal=0;
402 cnv->loopstretch=0;
403 cnv->dither=0;
404 cnv->ditherstretch=0;
405 cnv->flags|=HERMES_CONVERT_GENERIC;
406
407
408 /* Generic routines implement whole converters not scanline converters,
409 assign placeholders */
410
411 cnv->normal=NotApplicable;
412 cnv->stretch=NotApplicable;
413
414 // Calculate the jump table offset;
415 src_bits = (source->bits >> 3);
416 dest_bits = (dest->bits >> 3);
417 // Validate the offset
418 if ((src_bits <= 0) || (src_bits > 4) || (dest_bits <= 0) || (dest_bits > 4) ) return 0;
419 src_bits = src_bits - 1;
420 dest_bits = dest_bits - 1;
421
422 jptr = NULL;
423 if ((cnv->flags & HERMES_CONVERT_INVERSE_ALPHA) && (dest->a) && (tptr->jt_noalpha_alpha !=NULL))
424 {
425 jptr = tptr->jt_noalpha_alpha[src_bits] + dest_bits;
426 }
427 else if ((source->has_colorkey==1) && (dest->has_colorkey==1) && (tptr->jt_cc != NULL))
428 {
429 jptr = tptr->jt_cc[src_bits] + dest_bits;
430 }
431 else if ((source->has_colorkey==1) && dest->a && (tptr->jt_ca != NULL))
432 {
433 jptr = tptr->jt_ca[src_bits] + dest_bits;
434 }
435 else if (source->a && (dest->has_colorkey==1) && (tptr->jt_ac != NULL))
436 {
437 jptr = tptr->jt_ac[src_bits] + dest_bits;
438 }
439 else if (source->a && dest->a && (tptr->jt_ao != NULL))
440 {
441 jptr = tptr->jt_ao[src_bits] + dest_bits;
442 }
443 else if (source->a && (tptr->jt_aa != NULL))
444 {
445 jptr = tptr->jt_aa[src_bits] + dest_bits;
446 }
447 else if (source->has_colorkey==1 && (tptr->jt_co != NULL))
448 {
449 jptr = tptr->jt_co[src_bits] + dest_bits;
450 }
451 else if ( tptr->jt_copyonly != NULL)
452 {
453 jptr = tptr->jt_copyonly[src_bits] + dest_bits;
454 }
455
456 if (jptr) {
457 cnv->loopnormal = jptr->loopnormal;
458 cnv->loopstretch = jptr->loopstretch;
459 DEBUG_PRINT("Using Converter: %s\n", jptr->converter_name);
460 Hermes_FormatCopy(source,&cnv->source);
461 Hermes_FormatCopy(dest,&cnv->dest);
462 return 1;
463 }
464
465 /* No converter found, fail */
466
467 return 0;
468 }
469
470
471
472
Hermes_BlitterPalette(HermesHandle handle,HermesHandle sourcepal,HermesHandle destpal)473 int HERMES_API Hermes_BlitterPalette(HermesHandle handle,
474 HermesHandle sourcepal,
475 HermesHandle destpal)
476 {
477 if (handle<0 || handle>=LastConverter) return 0;
478 if (!ConverterList[handle]) return 0;
479
480 /* Fail silently if not indexed colour format */
481
482 if (!ConverterList[handle]->source.indexed) {
483 ConverterList[handle]->lookup=0;
484 return 1;
485 }
486
487 ConverterList[handle]->lookup=
488 Hermes_PaletteGetTable(sourcepal,&ConverterList[handle]->dest);
489
490 if (!ConverterList[handle]->lookup) return 0;
491
492 return 1;
493 }
494
495
Hermes_BlitterBlit(HermesHandle handle,void * s_pixels,int s_x,int s_y,int s_width,int s_height,int s_pitch,void * d_pixels,int d_x,int d_y,int d_width,int d_height,int d_pitch)496 int HERMES_API Hermes_BlitterBlit(HermesHandle handle,void *s_pixels,int s_x,
497 int s_y,int s_width,int s_height,
498 int s_pitch,void *d_pixels,int d_x,int d_y,
499 int d_width,int d_height,int d_pitch)
500 { HermesConverter *cnv;
501 HermesConverterInterface iface;
502
503 if (handle<0 || handle>=LastConverter) return 0;
504 cnv=ConverterList[handle];
505 if (!cnv) return 0;
506
507
508 /* Returns success if height or width is zero. This is debatable.. ! */
509
510 if (s_width<=0 || s_height<=0 || d_width<=0 || d_height<=0) return 1;
511
512 iface.s_pixels=(char8 *)s_pixels;
513 iface.s_width=s_width;
514 iface.s_height=s_height;
515 iface.s_add=s_pitch-s_width*(cnv->source.bits>>3);
516 iface.s_pitch=s_pitch;
517
518 iface.d_pixels=(char8 *)d_pixels;
519 iface.d_width=d_width;
520 iface.d_height=d_height;
521 iface.d_add=d_pitch-d_width*(cnv->dest.bits>>3);
522 iface.d_pitch=d_pitch;
523
524 iface.s_pixels+=s_y*s_pitch+s_x*(cnv->source.bits>>3);
525 iface.d_pixels+=d_y*d_pitch+d_x*(cnv->dest.bits>>3);
526
527 iface.s_has_colorkey = cnv->source.has_colorkey;
528 iface.d_has_colorkey = cnv->dest.has_colorkey;
529 iface.s_colorkey = cnv->source.colorkey;
530 iface.d_colorkey = cnv->dest.colorkey;
531
532 iface.lookup=cnv->lookup;
533
534
535 /* For generic converters, do some extra setup (find shifts, etc.)
536 TODO: Move that out of here and in the request routine ! */
537
538 if (cnv->flags&HERMES_CONVERT_GENERIC) {
539 Hermes_Calculate_Generic_Info(Hermes_Topbit(cnv->source.r),
540 Hermes_Topbit(cnv->source.g),
541 Hermes_Topbit(cnv->source.b),
542 Hermes_Topbit(cnv->source.a),
543 Hermes_Topbit(cnv->dest.r),
544 Hermes_Topbit(cnv->dest.g),
545 Hermes_Topbit(cnv->dest.b),
546 Hermes_Topbit(cnv->dest.a),
547 &iface.info);
548 iface.mask_r=cnv->dest.r;
549 iface.mask_g=cnv->dest.g;
550 iface.mask_b=cnv->dest.b;
551 iface.mask_a=cnv->dest.a;
552 iface.s_mask_a = cnv->source.a;
553 }
554
555
556 /* Check for dithering. This should not be in here but in request as well */
557
558 if (cnv->flags&HERMES_CONVERT_DITHER) {
559
560 /* If there is a ditherer, use it else fall back to normal */
561
562 if (cnv->dither)
563 cnv->loopnormal=cnv->dither;
564 }
565
566
567 /* Normal conversion */
568
569 if (s_width==d_width && s_height==d_height) {
570 if (!cnv->normal || !cnv->loopnormal) return 0;
571
572 /* Optimization
573 if (iface.s_add==0 && iface.d_add==0) {
574 iface.s_width *= s_height;
575 iface.d_width *= d_height;
576 iface.s_height = 1;
577 iface.d_height = 1;
578 }*/
579
580 iface.func=cnv->normal;
581 cnv->loopnormal(&iface);
582
583 return 1;
584 }
585 /* Stretch conversion */
586 else {
587 if (!cnv->stretch || !cnv->loopstretch) return 0;
588
589 iface.func=cnv->stretch;
590 cnv->loopstretch(&iface);
591 }
592
593 return 1;
594 }
595
596
597
598
599
600
601
602
603