Minor fixes to comments.
[AROS.git] / rom / graphics / bltbitmap.c
blob3aa533a6582c36c904e0b8469da88555d3901675
1 /*
2 Copyright © 1995-2011, 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 /* nlorentz: Also check for BMF_AROS_DISPLAYED flag which if set tells
121 that this is a HIDD bitmap and should be handled by the driver */
123 if ( srcBitMap->pad != 0 || destBitMap->pad != 0
124 || srcBitMap->Flags & BMF_SPECIALFMT || destBitMap->Flags & BMF_SPECIALFMT)
126 ULONG wSrc, wDest;
127 ULONG x;
128 ULONG depth;
129 struct monitor_driverdata *driver, *dst_driver;
130 OOP_Object *tmp_gc;
132 EnterFunc(bug("driver_BltBitMap()\n"));
134 /* bug("BltBitMap(%p, %d, %d, %p, %d, %d, %d, %d, %x)\n"
135 ,srcBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize, ySize, minterm);
139 wSrc = GetBitMapAttr( srcBitMap, BMA_WIDTH);
140 wDest = GetBitMapAttr(destBitMap, BMA_WIDTH);
142 /* Clip all blits */
144 depth = GetBitMapAttr ( srcBitMap, BMA_DEPTH);
145 x = GetBitMapAttr (destBitMap, BMA_DEPTH);
147 if (x < depth) depth = x;
149 /* Clip X and Y */
150 if (xSrc < 0)
152 xDest += -xSrc;
153 xSize -= -xSrc;
154 xSrc = 0;
157 if (ySrc < 0)
159 yDest += -ySrc;
160 ySize -= -ySrc;
161 ySrc = 0;
164 /* Clip width and height for source and dest */
165 if (ySrc + ySize > srcBitMap->Rows)
167 ySize = srcBitMap->Rows - ySrc;
170 if (yDest + ySize > destBitMap->Rows)
172 ySize = destBitMap->Rows - yDest;
175 if ((ULONG)(xSrc + xSize) >= wSrc)
177 xSize = wSrc - xSrc;
180 if ((ULONG)(xDest + xSize) >= wDest)
182 xSize = wDest - xDest;
185 /* If the size is illegal or we need not copy anything, return */
186 if (ySize <= 0 || xSize <= 0 || !mask) return 0;
189 * Select a driver to call
190 * Selection rules:
191 * 1. If one of drivers is fakegfx.hidd, we must use it in order
192 * to de-masquerade fakefb objects.
193 * 2. If one of drivers is our default software bitmap driver,
194 * we use another one, which can be an accelerated video driver.
196 driver = GET_BM_DRIVERDATA(srcBitMap);
197 dst_driver = GET_BM_DRIVERDATA(destBitMap);
199 if (driver == (struct monitor_driverdata *)CDD(GfxBase))
202 * If source bitmap is generic software one, we select destination bitmap.
203 * It can be either fakegfx or accelerated hardware driver.
205 driver = dst_driver;
207 else if (dst_driver->flags & DF_UseFakeGfx)
210 * If destination bitmap is fakegfx bitmap, we use its driver.
211 * Source one might be not fakegfx.
213 driver = dst_driver;
216 * If both tests failed, we use source driver. We know that source it not a
217 * generic software driver, and destionation is not fakegfx. So, source
218 * can be either fakegfx or hardware driver.
221 tmp_gc = obtain_cache_object(CDD(GfxBase)->gc_cache, GfxBase);
222 if (NULL != tmp_gc)
224 OOP_Object *srcbm_obj;
226 srcbm_obj = OBTAIN_HIDD_BM(srcBitMap);
227 if (NULL != srcbm_obj)
229 OOP_Object *dstbm_obj;
231 dstbm_obj = OBTAIN_HIDD_BM(destBitMap);
232 if (NULL != dstbm_obj)
235 int_bltbitmap(srcBitMap, srcbm_obj
236 , xSrc, ySrc
237 , destBitMap, dstbm_obj
238 , xDest, yDest
239 , xSize, ySize
240 , minterm
241 , driver->gfxhidd
242 , tmp_gc
243 , GfxBase);
244 update_bitmap(destBitMap, dstbm_obj, xDest, yDest, xSize, ySize, GfxBase);
246 RELEASE_HIDD_BM(dstbm_obj, destBitMap);
249 RELEASE_HIDD_BM(srcbm_obj, srcBitMap);
251 release_cache_object(CDD(GfxBase)->gc_cache, tmp_gc, GfxBase);
254 /* FIXME: dummy return value of 8 planes */
255 planecnt = 8;
258 else
260 ULONG wSrc, wDest;
261 ULONG x, y, plane;
262 ULONG depth;
263 PLANEPTR src, dest, temp;
265 wSrc = GetBitMapAttr( srcBitMap, BMA_WIDTH);
266 wDest = GetBitMapAttr(destBitMap, BMA_WIDTH);
267 temp = NULL;
269 depth = GetBitMapAttr ( srcBitMap, BMA_DEPTH);
270 x = GetBitMapAttr (destBitMap, BMA_DEPTH);
271 if (x < depth)
272 depth = x;
274 /* Clip X and Y */
275 if (xSrc < 0)
277 xDest += -xSrc;
278 xSize -= -xSrc;
279 xSrc = 0;
282 if (ySrc < 0)
284 yDest += -ySrc;
285 ySize -= -ySrc;
286 ySrc = 0;
289 /* Clip width and height for source and dest */
290 if (ySrc + ySize > srcBitMap->Rows)
292 ySize = srcBitMap->Rows - ySrc;
295 if (yDest + ySize > destBitMap->Rows)
297 ySize = destBitMap->Rows - yDest;
300 if ((ULONG)(xSrc + xSize) >= wSrc)
302 xSize = wSrc - xSrc;
305 if ((ULONG)(xDest + xSize) >= wDest)
307 xSize = wDest - xDest;
310 /* If the size is illegal or we need not copy anything, return */
311 if (ySize <= 0 || xSize <= 0 || !mask)
312 return 0;
314 planecnt = 0;
316 /* For all planes */
317 for (plane=0; plane<depth; plane ++)
319 /* Don't do anything if destination planeptr is NULL (means treat like
320 a plane with all zeros) or -1 (means treat like a plane with all ones) */
322 if ((destBitMap->Planes[plane] != NULL) && (destBitMap->Planes[plane] != (PLANEPTR)-1))
324 /* Copy this plane ? */
325 if ((1L << plane) & mask)
328 planecnt ++; /* count it */
330 for (y=0; y<(ULONG)ySize; y++)
332 src = srcBitMap->Planes[plane] + (y+ySrc) * srcBitMap->BytesPerRow;
333 dest = destBitMap->Planes[plane] + (y+yDest)*destBitMap->BytesPerRow;
336 If the source address is less or equal to
337 the destination address
339 if ((src <= dest && src+srcBitMap->BytesPerRow > dest)
340 || (dest <= src && dest+destBitMap->BytesPerRow > src)
343 if (!temp)
345 if (tempA)
346 temp = tempA;
347 else
348 temp = AllocMem (srcBitMap->BytesPerRow, MEMF_ANY);
350 if (!temp)
351 return 0;
354 memmove (temp, src, srcBitMap->BytesPerRow);
356 for (x=0; x<(ULONG)xSize; x++)
357 copyonepixel (temp, x+xSrc, dest, x+xDest, minterm);
359 else
361 for (x=0; x<(ULONG)xSize; x++)
362 copyonepixel (src, x+xSrc, dest, x+xDest, minterm);
365 } /* for (y=0; y<ySize; y++) */
367 } /* if ((1L << plane) & mask) */
369 } /* if dest plane != NULL and dest plane != -1 */
371 } /* for (plane=0; plane<depth; plane ++) */
373 if (temp && !tempA)
374 FreeMem (temp, srcBitMap->BytesPerRow);
377 return planecnt;
379 AROS_LIBFUNC_EXIT
381 } /* BltBitMap */
383 /****************************************************************************************/
385 static void copyonepixel (PLANEPTR src, ULONG xsrc, PLANEPTR dest, ULONG xdest,
386 ULONG minterm)
388 ULONG sByte, sSet;
389 ULONG dByte, dSet;
390 UBYTE sBit;
391 UBYTE dBit;
392 BOOL set;
394 if (src == NULL)
396 sSet = FALSE;
397 } else if (src == (PLANEPTR)-1)
399 sSet = TRUE;
400 } else {
401 sByte = xsrc >> 3;
402 sBit = 1L << (7 - (xsrc & 0x07));
403 sSet = (src[sByte] & sBit) != 0;
406 /* dest PLANEPTR here will never be NULL or -1 */
407 dByte = xdest >> 3;
408 dBit = 1L << (7 - (xdest & 0x07));
409 dSet = (dest[dByte] & dBit) != 0;
411 set = 0;
413 if (minterm & 0x0010)
415 if (!sSet && !dSet)
416 set = 1;
418 if (minterm & 0x0020)
420 if (!sSet && dSet)
421 set = 1;
423 if (minterm & 0x0040)
425 if (sSet && !dSet)
426 set = 1;
428 if (minterm & 0x0080)
430 if (sSet && dSet)
431 set = 1;
434 if (set)
435 dest[dByte] |= dBit;
436 else
437 dest[dByte] &= ~dBit;
440 /****************************************************************************************/