Autodoc formatting fixed.
[AROS.git] / rom / graphics / gfxfuncsupport.c
blob06b92295a7afa2e57d1bc9a75b9e0669c7a3c340
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
7 #include <aros/debug.h>
9 #include <cybergraphx/cybergraphics.h>
10 #include <graphics/rpattr.h>
11 #include <proto/layers.h>
12 #include <proto/exec.h>
13 #include <proto/graphics.h>
14 #include <proto/oop.h>
15 #include <clib/macros.h>
17 #include "graphics_intern.h"
18 #include "objcache.h"
19 #include "intregions.h"
20 #include "gfxfuncsupport.h"
21 #include "graphics_driver.h"
23 #define DEBUG_PLANARBM(x)
25 #define LayersBase (struct LayersBase *)(GfxBase->gb_LayersBase)
27 /****************************************************************************************/
29 OOP_Object *get_planarbm_object(struct BitMap *bitmap, struct GfxBase *GfxBase)
31 OOP_Object *pbm_obj;
33 DEBUG_PLANARBM(bug("get_planarbm_object()\n"));
34 pbm_obj = obtain_cache_object(CDD(GfxBase)->planarbm_cache, GfxBase);
36 if (NULL != pbm_obj)
39 DEBUG_PLANARBM(bug("Got cache object %p, class=%s, instoffset=%d\n"
40 , pbm_obj
41 , OOP_OCLASS(pbm_obj)->ClassNode.ln_Name
42 , OOP_OCLASS(pbm_obj)->InstOffset
43 ));
45 if (!HIDD_PlanarBM_SetBitMap(pbm_obj, bitmap))
47 DEBUG_PLANARBM(bug("!!! get_planarbm_object: HIDD_PlanarBM_SetBitMap FAILED !!!\n"));
48 release_cache_object(CDD(GfxBase)->planarbm_cache, pbm_obj, GfxBase);
49 pbm_obj = NULL;
53 else
55 DEBUG_PLANARBM(bug("!!! get_planarbm_object: obtain_cache_object FAILED !!!\n"));
58 return pbm_obj;
61 /****************************************************************************************/
63 static ULONG CallRenderFunc(RENDERFUNC render_func, APTR funcdata, WORD srcx, WORD srcy,
64 struct BitMap *bm, OOP_Object *gc, struct Rectangle *rect, BOOL do_update,
65 struct GfxBase *GfxBase)
67 OOP_Object *bm_obj = OBTAIN_HIDD_BM(bm);
68 ULONG pixwritten;
70 if (!bm_obj)
71 return 0;
73 pixwritten = render_func(funcdata, srcx, srcy, bm_obj, gc, rect, GfxBase);
75 if (do_update)
76 update_bitmap(bm, bm_obj, rect->MinX, rect->MinY,
77 rect->MaxX - rect->MinX + 1, rect->MaxY - rect->MinY + 1,
78 GfxBase);
80 RELEASE_HIDD_BM(bm_obj, bm);
81 return pixwritten;
84 ULONG do_render_func(struct RastPort *rp, Point *src, struct Rectangle *rr,
85 RENDERFUNC render_func, APTR funcdata,
86 BOOL do_update, BOOL get_special_info, struct GfxBase *GfxBase)
88 OOP_Object *gc = GetDriverData(rp, GfxBase);
90 return do_render_with_gc(rp, src, rr, render_func, funcdata, gc, do_update, get_special_info, GfxBase);
94 * GetDriverData() resets the GC to RastPort's values.
95 * This is another entry point which avoids that. Use it if you have already set up GC.
97 ULONG do_render_with_gc(struct RastPort *rp, Point *src, struct Rectangle *rr,
98 RENDERFUNC render_func, APTR funcdata, OOP_Object *gc,
99 BOOL do_update, BOOL get_special_info, struct GfxBase *GfxBase)
102 struct BitMap *bm = rp->BitMap;
103 struct Layer *L = rp->Layer;
104 struct Rectangle rp_clip_rectangle;
105 BOOL have_rp_cliprectangle;
106 WORD srcx, srcy;
107 LONG pixwritten = 0;
109 if (NULL != src)
111 srcx = src->x;
112 srcy = src->y;
113 } else
115 srcx = 0;
116 srcy = 0;
119 if (NULL == L)
121 /* No layer, probably a screen, but may be a user inited bitmap */
122 struct Rectangle torender = *rr;
124 have_rp_cliprectangle = GetRPClipRectangleForBitMap(rp, bm, &rp_clip_rectangle, GfxBase);
125 if (have_rp_cliprectangle && !(_AndRectRect(rr, &rp_clip_rectangle, &torender)))
127 return 0;
130 srcx += (torender.MinX - rr->MinX);
131 srcy += (torender.MinY - rr->MinY);
133 if (get_special_info)
135 RSI(funcdata)->curbm = rp->BitMap;
138 pixwritten = CallRenderFunc(render_func, funcdata, srcx, srcy,
139 bm, gc, &torender, do_update, GfxBase);
141 else
143 struct ClipRect *CR;
144 WORD xrel;
145 WORD yrel;
146 struct Rectangle torender, intersect;
148 LockLayerRom(L);
150 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
152 xrel = L->bounds.MinX;
153 yrel = L->bounds.MinY;
155 torender.MinX = rr->MinX + xrel - L->Scroll_X;
156 torender.MinY = rr->MinY + yrel - L->Scroll_Y;
157 torender.MaxX = rr->MaxX + xrel - L->Scroll_X;
158 torender.MaxY = rr->MaxY + yrel - L->Scroll_Y;
160 CR = L->ClipRect;
162 for (;NULL != CR; CR = CR->Next)
164 D(bug("Cliprect (%d, %d, %d, %d), lobs=%p\n",
165 CR->bounds.MinX, CR->bounds.MinY, CR->bounds.MaxX, CR->bounds.MaxY,
166 CR->lobs));
168 /* Does this cliprect intersect with area to rectfill ? */
169 if (_AndRectRect(&CR->bounds, &torender, &intersect))
171 if (!have_rp_cliprectangle || _AndRectRect(&rp_clip_rectangle, &intersect, &intersect))
173 WORD xoffset, yoffset;
175 xoffset = intersect.MinX - torender.MinX;
176 yoffset = intersect.MinY - torender.MinY;
178 if (NULL == CR->lobs)
180 if (get_special_info)
182 RSI(funcdata)->curbm = bm;
185 pixwritten += CallRenderFunc(render_func, funcdata, srcx + xoffset, srcy + yoffset,
186 bm, gc, &intersect, do_update, GfxBase);
188 else
190 /* Render into offscreen cliprect bitmap */
191 if (L->Flags & LAYERSIMPLE)
192 continue;
193 else if (L->Flags & LAYERSUPER)
195 D(bug("do_render_func(): Superbitmap not handled yet\n"));
197 else
200 if (get_special_info)
202 RSI(funcdata)->curbm = CR->BitMap;
205 intersect.MinX = intersect.MinX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX);
206 intersect.MinY = intersect.MinY - CR->bounds.MinY;
207 intersect.MaxX = intersect.MaxX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX);
208 intersect.MaxY = intersect.MaxY - CR->bounds.MinY;
210 pixwritten += CallRenderFunc(render_func, funcdata, srcx + xoffset, srcy + yoffset,
211 CR->BitMap, gc, &intersect, do_update, GfxBase);
214 } /* if (CR->lobs == NULL) */
216 } /* if it also intersects with possible rastport clip rectangle */
218 } /* if (cliprect intersects with area to render into) */
220 } /* for (each cliprect in the layer) */
222 UnlockLayerRom(L);
223 } /* if (rp->Layer) */
225 return pixwritten;
228 /****************************************************************************************/
230 static LONG CallPixelFunc(PIXELFUNC render_func, APTR funcdata, struct BitMap *bm, OOP_Object *gc,
231 WORD x, WORD y, BOOL do_update, struct GfxBase *GfxBase)
233 OOP_Object *bm_obj = OBTAIN_HIDD_BM(bm);
234 LONG retval;
236 if (!bm_obj)
237 return -1;
239 retval = render_func(funcdata, bm_obj, gc, x, y, GfxBase);
241 if (do_update)
242 update_bitmap(bm, bm_obj, x, y, 1, 1, GfxBase);
244 RELEASE_HIDD_BM(bm_obj, bm);
245 return retval;
248 ULONG do_pixel_func(struct RastPort *rp
249 , WORD x, WORD y
250 , PIXELFUNC render_func
251 , APTR funcdata
252 , BOOL do_update
253 , struct GfxBase *GfxBase)
255 struct BitMap *bm = rp->BitMap;
256 struct Layer *L = rp->Layer;
257 OOP_Object *gc;
258 struct Rectangle rp_clip_rectangle;
259 BOOL have_rp_cliprectangle;
260 ULONG retval = -1;
262 gc = GetDriverData(rp, GfxBase);
264 if (NULL == L)
266 have_rp_cliprectangle = GetRPClipRectangleForBitMap(rp, bm, &rp_clip_rectangle, GfxBase);
267 if (have_rp_cliprectangle && !_IsPointInRect(&rp_clip_rectangle, x, y))
269 return -1;
272 #if 0 /* With enabled BITMAP_CLIPPING this will be done automatically */
273 OOP_GetAttr(bm_obj, aHidd_BitMap_Width, &width);
274 OOP_GetAttr(bm_obj, aHidd_BitMap_Height, &height);
276 /* Check whether we it is inside the rastport */
277 if ( x < 0
278 || x >= width
279 || y < 0
280 || y >= height)
282 return -1;
284 #endif
286 /* This is a screen */
287 retval = CallPixelFunc(render_func, funcdata, bm, gc, x, y, do_update, GfxBase);
289 else
291 struct ClipRect *CR;
292 WORD absx, absy;
294 LockLayerRom( L );
296 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
298 CR = L->ClipRect;
300 absx = x + L->bounds.MinX - L->Scroll_X;
301 absy = y + L->bounds.MinY - L->Scroll_Y;
303 for (;NULL != CR; CR = CR->Next)
306 if ( absx >= CR->bounds.MinX
307 && absy >= CR->bounds.MinY
308 && absx <= CR->bounds.MaxX
309 && absy <= CR->bounds.MaxY )
312 if (!have_rp_cliprectangle || _IsPointInRect(&rp_clip_rectangle, absx, absy))
314 if (NULL == CR->lobs)
316 retval = CallPixelFunc(render_func, funcdata, bm, gc,
317 absx, absy, do_update, GfxBase);
319 else
321 /* This is the tricky one: render into offscreen cliprect bitmap */
322 if (L->Flags & LAYERSIMPLE)
324 /* We cannot do anything */
325 retval = 0;
328 else if (L->Flags & LAYERSUPER)
330 D(bug("driver_WriteRGBPixel(): Superbitmap not handled yet\n"));
332 else
334 retval = CallPixelFunc(render_func, funcdata, CR->BitMap, gc,
335 absx - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX),
336 absy - CR->bounds.MinY,
337 do_update, GfxBase);
338 } /* If (SMARTREFRESH cliprect) */
340 } /* if (intersecton inside hidden cliprect) */
342 } /* if point is also inside possible rastport clip rectangle */
344 /* The pixel was found and put inside one of the cliprects, just exit */
345 break;
347 } /* if (cliprect intersects with area we want to draw to) */
349 } /* while (cliprects to examine) */
350 UnlockLayerRom( L );
353 return retval;
356 /****************************************************************************************/
358 ULONG fillrect_render(APTR funcdata, WORD srcx, WORD srcy,
359 OOP_Object *dstbm_obj, OOP_Object *dst_gc,
360 struct Rectangle *rect, struct GfxBase *GfxBase)
362 HIDD_BM_FillRect(dstbm_obj, dst_gc, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY);
364 return (rect->MaxX - rect->MinX + 1) * (rect->MaxY - rect->MinY + 1);
367 /****************************************************************************************/
369 LONG fillrect_pendrmd(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
370 HIDDT_Pixel pix, HIDDT_DrawMode drmd, BOOL do_update, struct GfxBase *GfxBase)
372 OOP_Object *gc;
373 struct Rectangle rr;
375 gc = GetDriverData(rp, GfxBase);
376 GC_FG(gc) = pix;
377 GC_DRMD(gc) = drmd;
379 rr.MinX = x1;
380 rr.MinY = y1;
381 rr.MaxX = x2;
382 rr.MaxY = y2;
384 return do_render_with_gc(rp, NULL, &rr, fillrect_render, NULL, gc, do_update, FALSE, GfxBase);
387 /****************************************************************************************/
389 BOOL int_bltbitmap(struct BitMap *srcBitMap, OOP_Object *srcbm_obj, WORD xSrc, WORD ySrc,
390 struct BitMap *dstBitMap, OOP_Object *dstbm_obj, WORD xDest, WORD yDest,
391 WORD xSize, WORD ySize, ULONG minterm, OOP_Object *gfxhidd, OOP_Object *gc,
392 struct GfxBase *GfxBase)
394 HIDDT_DrawMode drmd;
396 ULONG srcflags = 0;
397 ULONG dstflags = 0;
399 BOOL src_colmap_set = FALSE;
400 BOOL dst_colmap_set = FALSE;
401 BOOL success = TRUE;
402 BOOL colmaps_ok = TRUE;
404 drmd = MINTERM_TO_GCDRMD(minterm);
406 /* We must lock any HIDD_BM_SetColorMap calls */
407 LOCK_BLIT
409 /* Try to get a CLUT for the bitmaps */
410 if (IS_HIDD_BM(srcBitMap))
412 //bug("driver_intbltbitmap: source is hidd bitmap\n");
413 if (NULL != HIDD_BM_COLMAP(srcBitMap))
415 //bug("driver_intbltbitmap: source has colormap\n");
416 srcflags |= FLG_HASCOLMAP;
418 srcflags |= GET_COLMOD_FLAGS(srcBitMap);
420 else
422 //bug("driver_intbltbitmap: source is amiga bitmap\n");
423 /* Amiga BM */
424 srcflags |= FLG_PALETTE;
427 if (IS_HIDD_BM(dstBitMap))
429 //bug("driver_intbltbitmap: dest is hidd bitmap\n");
430 if (NULL != HIDD_BM_COLMAP(dstBitMap))
432 //bug("driver_intbltbitmap: dest has colormap\n");
433 dstflags |= FLG_HASCOLMAP;
435 dstflags |= GET_COLMOD_FLAGS(dstBitMap);
437 else
439 //bug("driver_intbltbitmap: dest is amiga bitmap\n");
440 /* Amiga BM */
441 dstflags |= FLG_PALETTE;
444 if ( (srcflags == FLG_PALETTE || srcflags == FLG_STATICPALETTE))
446 /* palettized with no colmap. Neew to get a colmap from dest*/
447 if (dstflags == FLG_TRUECOLOR)
450 D(bug("!!! NO WAY GETTING PALETTE FOR src IN BltBitMap\n"));
451 colmaps_ok = FALSE;
452 success = FALSE;
455 else if (dstflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
458 /* Use the dest colmap for src */
459 HIDD_BM_SetColorMap(srcbm_obj, HIDD_BM_COLMAP(dstBitMap));
461 src_colmap_set = TRUE;
464 bug("Colormap:\n");
466 ULONG idx;
467 for (idx = 0; idx < 256; idx ++)
468 bug("[%d]=%d ", idx, HIDD_CM_GetPixel(HIDD_BM_COLMAP(dstBitMap), idx));
474 if ( (dstflags == FLG_PALETTE || dstflags == FLG_STATICPALETTE))
476 /* palettized with no pixtab. Nees to get a pixtab from dest*/
477 if (srcflags == FLG_TRUECOLOR)
479 D(bug("!!! NO WAY GETTING PALETTE FOR dst IN BltBitMap\n"));
480 colmaps_ok = FALSE;
481 success = FALSE;
484 else if (srcflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
487 /* Use the src colmap for dst */
488 HIDD_BM_SetColorMap(dstbm_obj, HIDD_BM_COLMAP(srcBitMap));
490 dst_colmap_set = TRUE;
494 if (colmaps_ok)
496 /* We need special treatment with drawmode Clear and
497 truecolor bitmaps, in order to set it to
498 colormap[0] instead of just 0
500 if ( (drmd == vHidd_GC_DrawMode_Clear)
501 && ( (dstflags & (FLG_TRUECOLOR | FLG_HASCOLMAP)) == (FLG_TRUECOLOR | FLG_HASCOLMAP) ))
504 HIDDT_DrawMode old_drmd;
505 IPTR old_fg;
507 struct TagItem frtags[] =
509 { aHidd_GC_Foreground , 0 },
510 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
511 { TAG_DONE }
514 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
515 OOP_GetAttr(gc, aHidd_GC_Foreground, &old_fg);
517 frtags[0].ti_Data = HIDD_BM_PIXTAB(dstBitMap)[0];
518 frtags[1].ti_Data = vHidd_GC_DrawMode_Copy;
520 OOP_SetAttrs(gc, frtags);
522 HIDD_BM_FillRect(dstbm_obj, gc
523 , xDest, yDest
524 , xDest + xSize - 1
525 , yDest + ySize - 1
528 frtags[0].ti_Data = old_fg;
529 frtags[1].ti_Data = old_drmd;
532 else
534 HIDDT_DrawMode old_drmd;
536 struct TagItem cbtags[] =
538 { aHidd_GC_DrawMode, 0 },
539 { TAG_DONE }
542 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
544 cbtags[0].ti_Data = drmd;
546 OOP_SetAttrs(gc, cbtags);
547 HIDD_Gfx_CopyBox(gfxhidd
548 , srcbm_obj
549 , xSrc, ySrc
550 , dstbm_obj
551 , xDest, yDest
552 , xSize, ySize
553 , gc
556 cbtags[0].ti_Data = drmd;
557 OOP_SetAttrs(gc, cbtags);
560 } /* if (colmaps_ok) */
562 if (src_colmap_set)
563 HIDD_BM_SetColorMap(srcbm_obj, NULL);
565 if (dst_colmap_set)
566 HIDD_BM_SetColorMap(dstbm_obj, NULL);
568 ULOCK_BLIT
570 return success;
574 /****************************************************************************************/
576 struct wp8_render_data
578 UBYTE *array;
579 ULONG modulo;
580 HIDDT_PixelLUT *pixlut;
583 static ULONG wp8_render(APTR wp8r_data, WORD srcx, WORD srcy, OOP_Object *dstbm_obj,
584 OOP_Object *dst_gc, struct Rectangle *rect, struct GfxBase *GfxBase)
586 struct wp8_render_data *wp8rd = wp8r_data;
587 WORD width = rect->MaxX - rect->MinX + 1;
588 WORD height = rect->MaxY - rect->MinY + 1;
590 HIDD_BM_PutImageLUT(dstbm_obj, dst_gc,
591 wp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wp8rd->modulo), wp8rd->modulo,
592 rect->MinX, rect->MinY, width, height, wp8rd->pixlut);
594 return width * height;
597 /****************************************************************************************/
599 LONG write_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
600 WORD xstart, WORD ystart, WORD xstop, WORD ystop,
601 HIDDT_PixelLUT *pixlut, BOOL do_update, struct GfxBase *GfxBase)
603 struct wp8_render_data wp8rd;
604 struct Rectangle rr;
605 OOP_Object *gc;
606 HIDDT_PixelLUT bm_lut;
608 /* If we haven't got a LUT, we obtain it from the bitmap */
609 if ((!pixlut) && IS_HIDD_BM(rp->BitMap))
611 bm_lut.entries = AROS_PALETTE_SIZE;
612 bm_lut.pixels = HIDD_BM_PIXTAB(rp->BitMap);
613 pixlut = &bm_lut;
615 #ifdef RTG_SANITY_CHECK
616 if ((!bm_lut.pixels) && (HIDD_BM_REALDEPTH(rp->BitMap) > 8))
618 D(bug("write_pixels_8: can't work on hicolor/truecolor screen without LUT"));
619 return 0;
621 #endif
624 gc = GetDriverData(rp, GfxBase);
625 GC_DRMD(gc) = vHidd_GC_DrawMode_Copy;
627 wp8rd.modulo = modulo;
628 wp8rd.array = array;
629 wp8rd.pixlut = pixlut;
631 rr.MinX = xstart;
632 rr.MinY = ystart;
633 rr.MaxX = xstop;
634 rr.MaxY = ystop;
636 return do_render_with_gc(rp, NULL, &rr, wp8_render, &wp8rd, gc, do_update, FALSE, GfxBase);
639 /****************************************************************************************/
641 struct wtp8_render_data
643 UBYTE *array;
644 ULONG modulo;
645 HIDDT_PixelLUT *pixlut;
646 UBYTE transparent;
649 static ULONG wtp8_render(APTR wtp8r_data, WORD srcx, WORD srcy, OOP_Object *dstbm_obj,
650 OOP_Object *dst_gc, struct Rectangle *rect, struct GfxBase *GfxBase)
652 struct wtp8_render_data *wtp8rd = wtp8r_data;
653 WORD width = rect->MaxX - rect->MinX + 1;
654 WORD height = rect->MaxY - rect->MinY + 1;
656 HIDD_BM_PutTranspImageLUT(dstbm_obj, dst_gc,
657 wtp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wtp8rd->modulo), wtp8rd->modulo,
658 rect->MinX, rect->MinY,width, height, wtp8rd->pixlut, wtp8rd->transparent);
660 return width * height;
662 /****************************************************************************************/
664 LONG write_transp_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
665 WORD xstart, WORD ystart, WORD xstop, WORD ystop,
666 HIDDT_PixelLUT *pixlut, UBYTE transparent,
667 BOOL do_update, struct GfxBase *GfxBase)
669 struct wtp8_render_data wtp8rd;
670 struct Rectangle rr;
671 OOP_Object *gc;
673 gc = GetDriverData(rp, GfxBase);
674 GC_DRMD(gc) = vHidd_GC_DrawMode_Copy;
676 wtp8rd.modulo = modulo;
677 wtp8rd.array = array;
678 wtp8rd.pixlut = pixlut;
679 wtp8rd.transparent = transparent;
681 rr.MinX = xstart;
682 rr.MinY = ystart;
683 rr.MaxX = xstop;
684 rr.MaxY = ystop;
686 return do_render_with_gc(rp, NULL, &rr, wtp8_render, &wtp8rd, gc, do_update, FALSE, GfxBase);
689 /****************************************************************************************/
692 ** General functions for moving blocks of data to or from HIDDs, be it pixelarrays
693 ** or bitmaps. They use a callback-function to get data from amiga/put data to amiga
694 ** bitmaps/pixelarrays
697 /****************************************************************************************/
699 /****************************************************************************************/
701 #define ENABLE_PROFILING 0
702 #define USE_OLD_MoveRaster 0
704 #define rdtscll(val) \
705 __asm__ __volatile__("rdtsc" : "=A" (val))
707 #if ENABLE_PROFILING && defined(__i386__)
710 #define AROS_BEGIN_PROFILING(context) \
712 unsigned long long _time1, _time2; \
713 char *_text = #context; \
714 rdtscll(_time1); \
717 #define AROS_END_PROFILING \
719 rdtscll(_time2); \
720 kprintf("%s: Ticks count: %u\n", _text, (unsigned long)(_time2 - _time1)); \
723 #else
725 #define AROS_BEGIN_PROFILING(context)
726 #define AROS_END_PROFILING
728 #endif
730 BOOL MoveRaster (struct RastPort * rp, WORD dx, WORD dy, WORD x1, WORD y1,
731 WORD x2, WORD y2, BOOL UpdateDamageList, struct GfxBase * GfxBase)
733 struct Layer *L = rp->Layer;
734 struct Rectangle ScrollRect;
735 struct Rectangle Rect;
737 if (0 == dx && 0 == dy)
738 return TRUE;
740 ScrollRect.MinX = x1;
741 ScrollRect.MinY = y1;
742 ScrollRect.MaxX = x2;
743 ScrollRect.MaxY = y2;
745 if (!L)
747 Rect = ScrollRect;
748 TranslateRect(&Rect, -dx, -dy);
749 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
751 BltBitMap(rp->BitMap,
752 Rect.MinX + dx,
753 Rect.MinY + dy,
754 rp->BitMap,
755 Rect.MinX,
756 Rect.MinY,
757 Rect.MaxX - Rect.MinX + 1,
758 Rect.MaxY - Rect.MinY + 1,
759 0xc0, /* copy */
760 0xff,
761 NULL );
764 else
766 struct ClipRect *SrcCR;
768 LockLayerRom(L);
770 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
772 /* Scroll the old damagelist within the scroll area */
773 ScrollRegion(L->DamageList, &ScrollRect, -dx, -dy);
776 /* The scrolling area is relative to the Layer, so make it relative to the screen */
777 TranslateRect(&ScrollRect, MinX(L), MinY(L));
779 /* The damage list will be formed by the now hidden layer's parts that will become visible due
780 to the scrolling procedure, thus we procede this way:
782 1) Calculate the invisible region out of the visible one, subtracting it from the
783 scrolling area
785 2) Scroll the invisible region by (-dx, -dy) and then subtract from it the not scrolled equivalent
787 The regions that we obtain after (2) is the new damage list
790 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
792 Rect = ScrollRect;
794 TranslateRect(&Rect, dx, dy);
796 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
798 struct Region *Damage = NewRegion();
800 if (Damage)
802 #if 1
803 BOOL res = OrRectRegion(Damage, &ScrollRect);
804 #else
805 BOOL res = OrRectRegion(Damage, &Rect);
806 #endif
807 if (!res)
809 DisposeRegion(Damage);
810 Damage = NULL;
814 if (Damage)
818 ClearRegionRegion(L->VisibleRegion, Damage)
820 Damage->RegionRectangle
823 struct Region Tmp;
825 We play sort of dirty here, by making assumptions about the internals of the
826 Region structure and the region handling functions, but we are allowed to do that,
827 aren't we? ;-)
830 Tmp = *Damage;
832 TranslateRect(Bounds(Damage), -dx, -dy);
836 ClearRegionRegion(&Tmp, Damage)
838 Damage->RegionRectangle
841 #if 1
842 AndRectRegion(Damage, &ScrollRect);
843 if (Damage->RegionRectangle)
844 #else
845 #endif
847 /* Join the new damage list with the old one */
848 TranslateRect(Bounds(Damage), -MinX(L), -MinY(L));
849 OrRegionRegion(Damage, L->DamageList);
851 L->Flags |= LAYERREFRESH;
856 DisposeRegion(Damage);
861 AROS_BEGIN_PROFILING(SortLayerCR)
863 if (LayersBase)
864 SortLayerCR(L, dx, dy);
866 AROS_END_PROFILING
868 AROS_BEGIN_PROFILING(Blitting loop)
870 #if USE_OLDMoveRaster
873 struct ClipRect *LastHiddenCR;
875 for (LastHiddenCR = NULL, SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
877 SrcCR->_p1 = LastHiddenCR;
879 if (SrcCR->lobs)
880 LastHiddenCR = SrcCR;
885 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
887 int cando = 0;
889 if (SrcCR->lobs && (L->Flags & LAYERSIMPLE))
891 continue;
894 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
896 TranslateRect(&Rect, -dx, -dy);
898 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
899 cando = 1;
902 if (cando)
904 /* Rect.Min(X|Y) are the coordinates to wich the rectangle has to be moved
905 Rect.Max(X|Y) - Rect.Max(X|Y) - 1 are the dimensions of this rectangle */
906 if (!SrcCR->_p1 && !SrcCR->lobs)
908 /* there are no hidden/obscured rectangles this recrtangle has to deal with*/
909 BltBitMap
911 rp->BitMap,
912 Rect.MinX + dx,
913 Rect.MinY + dy,
914 rp->BitMap,
915 Rect.MinX,
916 Rect.MinY,
917 Rect.MaxX - Rect.MinX + 1,
918 Rect.MaxY - Rect.MinY + 1,
919 0xc0, /* copy */
920 0xff,
921 NULL
924 else
926 struct BitMap *srcbm;
927 struct RegionRectangle *rr;
928 struct Region *RectRegion = NewRegion();
929 struct Rectangle Tmp;
930 struct ClipRect *HiddCR;
931 WORD corrsrcx, corrsrcy;
932 BOOL dosrcsrc;
934 if (!RectRegion)
935 goto failexit;
937 if (!OrRectRegion(&Rect, RectRegion))
939 DisposeRegion(RectRegion);
940 goto failexit;
943 if (SrcCR->lobs)
945 if (L->Flags & LAYERSUPER)
947 corrsrcx = - MinX(L) - L->Scroll_X;
948 corrsrcy = - MinY(L) - L->Scroll_Y;
950 else
952 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
953 corrsrcy = - MinY(SrcCR);
955 srcbm = SrcCR->BitMap;
957 else
959 corrsrcx = 0;
960 corrsrcy = 0;
961 srcbm = rp->BitMap;
964 for (HiddCR = SrcCR->_p1; HiddCR; HiddCR = HiddCR->_p1)
966 if (_AndRectRect(Bounds(RectRegion), Bounds(HiddCR), &Tmp))
968 if (!(L->Flags & LAYERSIMPLE))
970 WORD corrdstx, corrdsty;
972 if (L->Flags & LAYERSUPER)
974 corrdstx = - MinX(L) - L->Scroll_X;
975 corrdsty = - MinY(L) - L->Scroll_Y;
977 else
979 /* Smart layer */
980 corrdstx = - MinX(HiddCR) + ALIGN_OFFSET(MinX(HiddCR));
981 corrdsty = - MinY(HiddCR);
985 BltBitMap
987 srcbm,
988 Tmp.MinX + corrsrcx + dx,
989 Tmp.MinY + corrsrcy + dy,
990 HiddCR->BitMap,
991 Tmp.MinX + corrdstx,
992 Tmp.MinY + corrdsty,
993 Tmp.MaxX - Tmp.MinX + 1,
994 Tmp.MaxY - Tmp.MinY + 1,
995 0xc0, /* copy */
996 0xff,
997 NULL
1001 if (!ClearRectRegion(RectRegion, &Tmp))
1003 DisposeRegion(RectRegion);
1004 goto failexit;
1009 if ((dosrcsrc = _AndRectRect(Bounds(SrcCR), &Rect, &Tmp)))
1011 if (!ClearRectRegion(RectRegion, &Tmp))
1013 DisposeRegion(RectRegion);
1014 goto failexit;
1018 for (rr = RectRegion->RegionRectangle; rr; rr = rr->Next)
1020 BltBitMap
1022 srcbm,
1023 MinX(rr) + MinX(RectRegion) + corrsrcx + dx,
1024 MinY(rr) + MinY(RectRegion) + corrsrcy + dy,
1025 rp->BitMap,
1026 MinX(rr) + MinX(RectRegion),
1027 MinY(rr) + MinY(RectRegion),
1028 Width(rr),
1029 Height(rr),
1030 0xc0, /* copy */
1031 0xff,
1032 NULL
1036 if (dosrcsrc)
1038 BltBitMap
1040 srcbm,
1041 Tmp.MinX + corrsrcx + dx,
1042 Tmp.MinY + corrsrcy + dy,
1043 srcbm,
1044 Tmp.MinX + corrsrcx,
1045 Tmp.MinY + corrsrcy,
1046 Tmp.MaxX - Tmp.MinX + 1,
1047 Tmp.MaxY - Tmp.MinY + 1,
1048 0xc0, /* copy */
1049 0xff,
1050 NULL
1055 DisposeRegion(RectRegion);
1060 #else
1062 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
1064 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
1066 TranslateRect(&Rect, -dx, -dy);
1068 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1070 struct BitMap *srcbm;
1071 struct ClipRect *DstCR;
1072 WORD corrsrcx, corrsrcy;
1073 ULONG area;
1075 if (SrcCR->lobs)
1077 if (L->Flags & LAYERSIMPLE) continue;
1079 if (L->Flags & LAYERSUPER)
1081 corrsrcx = - MinX(L) - L->Scroll_X;
1082 corrsrcy = - MinY(L) - L->Scroll_Y;
1084 else
1086 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
1087 corrsrcy = - MinY(SrcCR);
1089 srcbm = SrcCR->BitMap;
1091 else
1093 corrsrcx = 0;
1094 corrsrcy = 0;
1095 srcbm = rp->BitMap;
1098 area = (Rect.MaxX - Rect.MinX + 1) * (Rect.MaxY - Rect.MinY + 1);
1100 for (DstCR = L->ClipRect ; area && DstCR; DstCR = DstCR->Next)
1102 struct Rectangle Rect2;
1104 if (_AndRectRect(Bounds(DstCR), &Rect, &Rect2))
1106 struct BitMap *dstbm;
1107 WORD corrdstx, corrdsty;
1109 area -= (Rect2.MaxX - Rect2.MinX + 1) * (Rect2.MaxY - Rect2.MinY + 1);
1111 if (DstCR->lobs)
1113 if (L->Flags & LAYERSIMPLE) continue;
1115 if (L->Flags & LAYERSUPER)
1117 corrdstx = - MinX(L) - L->Scroll_X;
1118 corrdsty = - MinY(L) - L->Scroll_Y;
1120 else
1122 corrdstx = - MinX(DstCR) + ALIGN_OFFSET(MinX(DstCR));
1123 corrdsty = - MinY(DstCR);
1125 dstbm = DstCR->BitMap;
1127 else
1129 corrdstx = 0;
1130 corrdsty = 0;
1131 dstbm = rp->BitMap;
1134 BltBitMap
1136 srcbm,
1137 Rect2.MinX + corrsrcx + dx,
1138 Rect2.MinY + corrsrcy + dy,
1139 dstbm,
1140 Rect2.MinX + corrdstx,
1141 Rect2.MinY + corrdsty,
1142 Rect2.MaxX - Rect2.MinX + 1,
1143 Rect2.MaxY - Rect2.MinY + 1,
1144 0xC0,
1145 0xFF,
1146 NULL
1153 #endif
1154 AROS_END_PROFILING
1156 UnlockLayerRom(L);
1159 return TRUE;
1162 /****************************************************************************************/
1164 BOOL GetRPClipRectangleForRect(struct RastPort *rp, struct Rectangle *rect, struct Rectangle *r)
1166 struct gfx_driverdata *dd = ObtainDriverData(rp);
1168 if (dd && dd->dd_ClipRectangleFlags & RPCRF_VALID)
1170 *r = dd->dd_ClipRectangle;
1172 if (dd->dd_ClipRectangleFlags & RPCRF_RELRIGHT)
1174 r->MaxX += rect->MaxX - rect->MinX;
1177 if (dd->dd_ClipRectangleFlags & RPCRF_RELBOTTOM)
1179 r->MaxY += rect->MaxY - rect->MinY;
1182 r->MinX += rect->MinX;
1183 r->MinY += rect->MinY;
1184 r->MaxX += rect->MinX;
1185 r->MaxY += rect->MinY;
1187 return TRUE;
1190 return FALSE;
1193 /****************************************************************************************/
1195 BOOL GetRPClipRectangleForBitMap(struct RastPort *rp, struct BitMap *bm,
1196 struct Rectangle *r, struct GfxBase *GfxBase)
1198 struct Rectangle bm_rect;
1199 BOOL res;
1201 bm_rect.MinX = 0;
1202 bm_rect.MinY = 0;
1203 bm_rect.MaxX = GetBitMapAttr(bm, BMA_WIDTH) - 1;
1204 bm_rect.MaxY = GetBitMapAttr(bm, BMA_HEIGHT) - 1;
1206 res = GetRPClipRectangleForRect(rp, &bm_rect, r);
1208 #if BITMAP_CLIPPING
1209 if (!res)
1212 * Set the rectangle to total bitmap size. This prevents trashing memory
1213 * by hitting unallocated memory in HIDDs. They don't check bitmap bounds.
1215 *r = bm_rect;
1216 res = TRUE;
1218 #endif
1220 return res;