Documented GVF_SAVE_VAR alongside other flags, and removed a query/doubt
[AROS.git] / rom / graphics / bltbitmap.c
blob2b3d3726de418aabfac52f18c817f3147be08541
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Copy a rectangle in a bitmap to another place or another bitmap.
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <exec/memory.h>
11 #include <graphics/gfx.h>
12 #include <proto/exec.h>
14 #include "graphics_intern.h"
15 #include "gfxfuncsupport.h"
16 #include "objcache.h"
18 static void copyonepixel (PLANEPTR src, ULONG xsrc, PLANEPTR dest,
19 ULONG xdest, ULONG minterm);
21 /*****************************************************************************
23 NAME */
24 #include <graphics/gfx.h>
25 #include <proto/graphics.h>
27 AROS_LH11(LONG, BltBitMap,
29 /* SYNOPSIS */
30 AROS_LHA(struct BitMap *, srcBitMap, A0),
31 AROS_LHA(LONG , xSrc, D0),
32 AROS_LHA(LONG , ySrc, D1),
33 AROS_LHA(struct BitMap *, destBitMap, A1),
34 AROS_LHA(LONG , xDest, D2),
35 AROS_LHA(LONG , yDest, D3),
36 AROS_LHA(LONG , xSize, D4),
37 AROS_LHA(LONG , ySize, D5),
38 AROS_LHA(ULONG , minterm, D6),
39 AROS_LHA(ULONG , mask, D7),
40 AROS_LHA(PLANEPTR , tempA, A2),
42 /* LOCATION */
43 struct GfxBase *, GfxBase, 5, Graphics)
45 /* FUNCTION
46 Moves a part of a bitmap around or into another bitmap.
48 INPUTS
49 srcBitMap - Copy from this bitmap.
50 xSrc, ySrc - This is the upper left corner of the area to copy.
51 destBitMap - Copy to this bitmap. May be the same as srcBitMap.
52 xDest, yDest - Upper left corner where to place the copy
53 xSize, ySize - The size of the area to copy
54 minterm - How to copy. Most useful values are 0x00C0 for a vanilla
55 copy, 0x0030 to invert the source and then copy or 0x0050
56 to ignore the source and just invert the destination. If
57 you want to calculate other values, then you must know that
58 channel A is set, if you are inside the rectangle, channel
59 B is the source and channel C is the destination of the
60 rectangle.
62 Bit ABC
63 0 000
64 1 001
65 2 010
66 3 011
67 4 100
68 5 101
69 6 110
70 7 111
72 So 0x00C0 means: D is set if one is inside the rectangle
73 (A is set) and B (the source) is set and cleared otherwise.
75 To fill the rectangle, you would want to set D when A is
76 set, so the value is 0x00F0.
78 mask - Which planes should be copied. Typically, you should set
79 this to ~0L.
80 tempA - If the copy overlaps exactly to the left or right (i.e. the
81 scan line addresses overlap), and tempA is non-zero, it
82 points to enough chip accessible memory to hold a line of a
83 source for the blit (i.e. CHIP RAM). BltBitMap will allocate
84 (and free) the needed TempA if none is provided and one is
85 needed. Blit overlap is determined from the relation of
86 the first non-masked planes in the source and destination
87 bit maps.
89 RESULT
90 The number of planes actually involved in the blit.
92 NOTES
93 If a special hardware is available, this function will use it.
95 As a special case, plane pointers of destBitMap can contain NULL
96 or -1, which will act as if the plane was filled with 0's or 1's,
97 respectively.
99 EXAMPLE
101 BUGS
103 SEE ALSO
104 ClipBlit(), BltBitMapRastPort()
106 INTERNALS
108 HISTORY
110 *****************************************************************************/
112 AROS_LIBFUNC_INIT
113 LONG planecnt;
115 FIX_GFXCOORD(xSrc);
116 FIX_GFXCOORD(ySrc);
117 FIX_GFXCOORD(xDest);
118 FIX_GFXCOORD(yDest);
120 D(bug("BltBitMap(%p, %d, %d, %p, %d, %d, %d, %d, %x)\n"
121 ,srcBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize, ySize, minterm));
123 if (IS_HIDD_BM(srcBitMap) || IS_HIDD_BM(destBitMap))
125 ULONG wSrc, wDest;
126 ULONG x;
127 ULONG depth;
128 struct monitor_driverdata *driver, *dst_driver;
129 OOP_Object *tmp_gc;
131 EnterFunc(bug("driver_BltBitMap()\n"));
133 wSrc = GetBitMapAttr( srcBitMap, BMA_WIDTH);
134 wDest = GetBitMapAttr(destBitMap, BMA_WIDTH);
136 /* Clip all blits */
138 depth = GetBitMapAttr ( srcBitMap, BMA_DEPTH);
139 x = GetBitMapAttr (destBitMap, BMA_DEPTH);
141 if (x < depth) depth = x;
143 /* Clip X and Y */
144 if (xSrc < 0)
146 xDest += -xSrc;
147 xSize -= -xSrc;
148 xSrc = 0;
151 if (ySrc < 0)
153 yDest += -ySrc;
154 ySize -= -ySrc;
155 ySrc = 0;
158 /* Clip width and height for source and dest */
159 if (ySrc + ySize > srcBitMap->Rows)
161 ySize = srcBitMap->Rows - ySrc;
164 if (yDest + ySize > destBitMap->Rows)
166 ySize = destBitMap->Rows - yDest;
169 if ((ULONG)(xSrc + xSize) >= wSrc)
171 xSize = wSrc - xSrc;
174 if ((ULONG)(xDest + xSize) >= wDest)
176 xSize = wDest - xDest;
179 /* If the size is illegal or we need not copy anything, return */
180 if (ySize <= 0 || xSize <= 0 || !mask) return 0;
183 * Select a driver to call
184 * Selection rules:
185 * 1. If one of drivers is fakegfx.hidd, we must use it in order
186 * to de-masquerade fakefb objects.
187 * 2. If one of drivers is our default software bitmap driver,
188 * we use another one, which can be an accelerated video driver.
190 driver = GET_BM_DRIVERDATA(srcBitMap);
191 dst_driver = GET_BM_DRIVERDATA(destBitMap);
193 if (driver == (struct monitor_driverdata *)CDD(GfxBase))
196 * If source bitmap is generic software one, we select destination bitmap.
197 * It can be either fakegfx or accelerated hardware driver.
199 driver = dst_driver;
201 else if (dst_driver->flags & DF_UseFakeGfx)
204 * If destination bitmap is fakegfx bitmap, we use its driver.
205 * Source one might be not fakegfx.
207 driver = dst_driver;
210 * If both tests failed, we use source driver. We know that source it not a
211 * generic software driver, and destionation is not fakegfx. So, source
212 * can be either fakegfx or hardware driver.
215 tmp_gc = obtain_cache_object(CDD(GfxBase)->gc_cache, GfxBase);
216 if (NULL != tmp_gc)
218 OOP_Object *srcbm_obj;
220 srcbm_obj = OBTAIN_HIDD_BM(srcBitMap);
221 if (NULL != srcbm_obj)
223 OOP_Object *dstbm_obj;
225 dstbm_obj = OBTAIN_HIDD_BM(destBitMap);
226 if (NULL != dstbm_obj)
229 int_bltbitmap(srcBitMap, srcbm_obj
230 , xSrc, ySrc
231 , destBitMap, dstbm_obj
232 , xDest, yDest
233 , xSize, ySize
234 , minterm
235 , driver->gfxhidd
236 , tmp_gc
237 , GfxBase);
238 update_bitmap(destBitMap, dstbm_obj, xDest, yDest, xSize, ySize, GfxBase);
240 RELEASE_HIDD_BM(dstbm_obj, destBitMap);
243 RELEASE_HIDD_BM(srcbm_obj, srcBitMap);
245 release_cache_object(CDD(GfxBase)->gc_cache, tmp_gc, GfxBase);
248 /* FIXME: dummy return value of 8 planes */
249 planecnt = 8;
252 else
254 ULONG wSrc, wDest;
255 ULONG x, y, plane;
256 ULONG depth;
257 PLANEPTR src, dest, temp;
259 wSrc = GetBitMapAttr( srcBitMap, BMA_WIDTH);
260 wDest = GetBitMapAttr(destBitMap, BMA_WIDTH);
261 temp = NULL;
263 depth = GetBitMapAttr ( srcBitMap, BMA_DEPTH);
264 x = GetBitMapAttr (destBitMap, BMA_DEPTH);
265 if (x < depth)
266 depth = x;
268 /* Clip X and Y */
269 if (xSrc < 0)
271 xDest += -xSrc;
272 xSize -= -xSrc;
273 xSrc = 0;
276 if (ySrc < 0)
278 yDest += -ySrc;
279 ySize -= -ySrc;
280 ySrc = 0;
283 /* Clip width and height for source and dest */
284 if (ySrc + ySize > srcBitMap->Rows)
286 ySize = srcBitMap->Rows - ySrc;
289 if (yDest + ySize > destBitMap->Rows)
291 ySize = destBitMap->Rows - yDest;
294 if ((ULONG)(xSrc + xSize) >= wSrc)
296 xSize = wSrc - xSrc;
299 if ((ULONG)(xDest + xSize) >= wDest)
301 xSize = wDest - xDest;
304 /* If the size is illegal or we need not copy anything, return */
305 if (ySize <= 0 || xSize <= 0 || !mask)
306 return 0;
308 planecnt = 0;
310 /* For all planes */
311 for (plane=0; plane<depth; plane ++)
313 /* Don't do anything if destination planeptr is NULL (means treat like
314 a plane with all zeros) or -1 (means treat like a plane with all ones) */
316 if ((destBitMap->Planes[plane] != NULL) && (destBitMap->Planes[plane] != (PLANEPTR)-1))
318 /* Copy this plane ? */
319 if ((1L << plane) & mask)
322 planecnt ++; /* count it */
324 for (y=0; y<(ULONG)ySize; y++)
326 src = srcBitMap->Planes[plane] + (y+ySrc) * srcBitMap->BytesPerRow;
327 dest = destBitMap->Planes[plane] + (y+yDest)*destBitMap->BytesPerRow;
330 If the source address is less or equal to
331 the destination address
333 if ((src <= dest && src+srcBitMap->BytesPerRow > dest)
334 || (dest <= src && dest+destBitMap->BytesPerRow > src)
337 if (!temp)
339 if (tempA)
340 temp = tempA;
341 else
342 temp = AllocMem (srcBitMap->BytesPerRow, MEMF_ANY);
344 if (!temp)
345 return 0;
348 memmove (temp, src, srcBitMap->BytesPerRow);
350 for (x=0; x<(ULONG)xSize; x++)
351 copyonepixel (temp, x+xSrc, dest, x+xDest, minterm);
353 else
355 for (x=0; x<(ULONG)xSize; x++)
356 copyonepixel (src, x+xSrc, dest, x+xDest, minterm);
359 } /* for (y=0; y<ySize; y++) */
361 } /* if ((1L << plane) & mask) */
363 } /* if dest plane != NULL and dest plane != -1 */
365 } /* for (plane=0; plane<depth; plane ++) */
367 if (temp && !tempA)
368 FreeMem (temp, srcBitMap->BytesPerRow);
371 return planecnt;
373 AROS_LIBFUNC_EXIT
375 } /* BltBitMap */
377 /****************************************************************************************/
379 static void copyonepixel (PLANEPTR src, ULONG xsrc, PLANEPTR dest, ULONG xdest,
380 ULONG minterm)
382 ULONG sByte, sSet;
383 ULONG dByte, dSet;
384 UBYTE sBit;
385 UBYTE dBit;
386 BOOL set;
388 if (src == NULL)
390 sSet = FALSE;
391 } else if (src == (PLANEPTR)-1)
393 sSet = TRUE;
394 } else {
395 sByte = xsrc >> 3;
396 sBit = 1L << (7 - (xsrc & 0x07));
397 sSet = (src[sByte] & sBit) != 0;
400 /* dest PLANEPTR here will never be NULL or -1 */
401 dByte = xdest >> 3;
402 dBit = 1L << (7 - (xdest & 0x07));
403 dSet = (dest[dByte] & dBit) != 0;
405 set = 0;
407 if (minterm & 0x0010)
409 if (!sSet && !dSet)
410 set = 1;
412 if (minterm & 0x0020)
414 if (!sSet && dSet)
415 set = 1;
417 if (minterm & 0x0040)
419 if (sSet && !dSet)
420 set = 1;
422 if (minterm & 0x0080)
424 if (sSet && dSet)
425 set = 1;
428 if (set)
429 dest[dByte] |= dBit;
430 else
431 dest[dByte] &= ~dBit;
434 /****************************************************************************************/