Added basic implementation of destroying a GPT table: just delete the
[AROS.git] / rom / graphics / gfxfuncsupport.c
blobffdd61adc8d2a814da39a51812c2f6534ed1cdb4
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
8 #include <cybergraphx/cybergraphics.h>
9 #include <graphics/rpattr.h>
10 #include <proto/exec.h>
11 #include <proto/graphics.h>
12 #include <proto/layers.h>
13 #include <proto/oop.h>
14 #include <clib/macros.h>
16 #include "graphics_intern.h"
17 #include "objcache.h"
18 #include "intregions.h"
19 #include "gfxfuncsupport.h"
20 #include "graphics_driver.h"
22 #define DEBUG 0
23 #include <aros/debug.h>
25 #define DEBUG_PLANARBM(x)
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 #define LayersBase (struct LayersBase *)(GfxBase->gb_LayersBase)
864 SortLayerCR(L, dx, dy);
865 #undef LayersBase
867 AROS_END_PROFILING
869 AROS_BEGIN_PROFILING(Blitting loop)
871 #if USE_OLDMoveRaster
874 struct ClipRect *LastHiddenCR;
876 for (LastHiddenCR = NULL, SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
878 SrcCR->_p1 = LastHiddenCR;
880 if (SrcCR->lobs)
881 LastHiddenCR = SrcCR;
886 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
888 int cando = 0;
890 if (SrcCR->lobs && (L->Flags & LAYERSIMPLE))
892 continue;
895 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
897 TranslateRect(&Rect, -dx, -dy);
899 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
900 cando = 1;
903 if (cando)
905 /* Rect.Min(X|Y) are the coordinates to wich the rectangle has to be moved
906 Rect.Max(X|Y) - Rect.Max(X|Y) - 1 are the dimensions of this rectangle */
907 if (!SrcCR->_p1 && !SrcCR->lobs)
909 /* there are no hidden/obscured rectangles this recrtangle has to deal with*/
910 BltBitMap
912 rp->BitMap,
913 Rect.MinX + dx,
914 Rect.MinY + dy,
915 rp->BitMap,
916 Rect.MinX,
917 Rect.MinY,
918 Rect.MaxX - Rect.MinX + 1,
919 Rect.MaxY - Rect.MinY + 1,
920 0xc0, /* copy */
921 0xff,
922 NULL
925 else
927 struct BitMap *srcbm;
928 struct RegionRectangle *rr;
929 struct Region *RectRegion = NewRegion();
930 struct Rectangle Tmp;
931 struct ClipRect *HiddCR;
932 WORD corrsrcx, corrsrcy;
933 BOOL dosrcsrc;
935 if (!RectRegion)
936 goto failexit;
938 if (!OrRectRegion(&Rect, RectRegion))
940 DisposeRegion(RectRegion);
941 goto failexit;
944 if (SrcCR->lobs)
946 if (L->Flags & LAYERSUPER)
948 corrsrcx = - MinX(L) - L->Scroll_X;
949 corrsrcy = - MinY(L) - L->Scroll_Y;
951 else
953 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
954 corrsrcy = - MinY(SrcCR);
956 srcbm = SrcCR->BitMap;
958 else
960 corrsrcx = 0;
961 corrsrcy = 0;
962 srcbm = rp->BitMap;
965 for (HiddCR = SrcCR->_p1; HiddCR; HiddCR = HiddCR->_p1)
967 if (_AndRectRect(Bounds(RectRegion), Bounds(HiddCR), &Tmp))
969 if (!(L->Flags & LAYERSIMPLE))
971 WORD corrdstx, corrdsty;
973 if (L->Flags & LAYERSUPER)
975 corrdstx = - MinX(L) - L->Scroll_X;
976 corrdsty = - MinY(L) - L->Scroll_Y;
978 else
980 /* Smart layer */
981 corrdstx = - MinX(HiddCR) + ALIGN_OFFSET(MinX(HiddCR));
982 corrdsty = - MinY(HiddCR);
986 BltBitMap
988 srcbm,
989 Tmp.MinX + corrsrcx + dx,
990 Tmp.MinY + corrsrcy + dy,
991 HiddCR->BitMap,
992 Tmp.MinX + corrdstx,
993 Tmp.MinY + corrdsty,
994 Tmp.MaxX - Tmp.MinX + 1,
995 Tmp.MaxY - Tmp.MinY + 1,
996 0xc0, /* copy */
997 0xff,
998 NULL
1002 if (!ClearRectRegion(RectRegion, &Tmp))
1004 DisposeRegion(RectRegion);
1005 goto failexit;
1010 if ((dosrcsrc = _AndRectRect(Bounds(SrcCR), &Rect, &Tmp)))
1012 if (!ClearRectRegion(RectRegion, &Tmp))
1014 DisposeRegion(RectRegion);
1015 goto failexit;
1019 for (rr = RectRegion->RegionRectangle; rr; rr = rr->Next)
1021 BltBitMap
1023 srcbm,
1024 MinX(rr) + MinX(RectRegion) + corrsrcx + dx,
1025 MinY(rr) + MinY(RectRegion) + corrsrcy + dy,
1026 rp->BitMap,
1027 MinX(rr) + MinX(RectRegion),
1028 MinY(rr) + MinY(RectRegion),
1029 Width(rr),
1030 Height(rr),
1031 0xc0, /* copy */
1032 0xff,
1033 NULL
1037 if (dosrcsrc)
1039 BltBitMap
1041 srcbm,
1042 Tmp.MinX + corrsrcx + dx,
1043 Tmp.MinY + corrsrcy + dy,
1044 srcbm,
1045 Tmp.MinX + corrsrcx,
1046 Tmp.MinY + corrsrcy,
1047 Tmp.MaxX - Tmp.MinX + 1,
1048 Tmp.MaxY - Tmp.MinY + 1,
1049 0xc0, /* copy */
1050 0xff,
1051 NULL
1056 DisposeRegion(RectRegion);
1061 #else
1063 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
1065 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
1067 TranslateRect(&Rect, -dx, -dy);
1069 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1071 struct BitMap *srcbm;
1072 struct ClipRect *DstCR;
1073 WORD corrsrcx, corrsrcy;
1074 ULONG area;
1076 if (SrcCR->lobs)
1078 if (L->Flags & LAYERSIMPLE) continue;
1080 if (L->Flags & LAYERSUPER)
1082 corrsrcx = - MinX(L) - L->Scroll_X;
1083 corrsrcy = - MinY(L) - L->Scroll_Y;
1085 else
1087 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
1088 corrsrcy = - MinY(SrcCR);
1090 srcbm = SrcCR->BitMap;
1092 else
1094 corrsrcx = 0;
1095 corrsrcy = 0;
1096 srcbm = rp->BitMap;
1099 area = (Rect.MaxX - Rect.MinX + 1) * (Rect.MaxY - Rect.MinY + 1);
1101 for (DstCR = L->ClipRect ; area && DstCR; DstCR = DstCR->Next)
1103 struct Rectangle Rect2;
1105 if (_AndRectRect(Bounds(DstCR), &Rect, &Rect2))
1107 struct BitMap *dstbm;
1108 WORD corrdstx, corrdsty;
1110 area -= (Rect2.MaxX - Rect2.MinX + 1) * (Rect2.MaxY - Rect2.MinY + 1);
1112 if (DstCR->lobs)
1114 if (L->Flags & LAYERSIMPLE) continue;
1116 if (L->Flags & LAYERSUPER)
1118 corrdstx = - MinX(L) - L->Scroll_X;
1119 corrdsty = - MinY(L) - L->Scroll_Y;
1121 else
1123 corrdstx = - MinX(DstCR) + ALIGN_OFFSET(MinX(DstCR));
1124 corrdsty = - MinY(DstCR);
1126 dstbm = DstCR->BitMap;
1128 else
1130 corrdstx = 0;
1131 corrdsty = 0;
1132 dstbm = rp->BitMap;
1135 BltBitMap
1137 srcbm,
1138 Rect2.MinX + corrsrcx + dx,
1139 Rect2.MinY + corrsrcy + dy,
1140 dstbm,
1141 Rect2.MinX + corrdstx,
1142 Rect2.MinY + corrdsty,
1143 Rect2.MaxX - Rect2.MinX + 1,
1144 Rect2.MaxY - Rect2.MinY + 1,
1145 0xC0,
1146 0xFF,
1147 NULL
1154 #endif
1155 AROS_END_PROFILING
1157 UnlockLayerRom(L);
1160 return TRUE;
1163 /****************************************************************************************/
1165 BOOL GetRPClipRectangleForRect(struct RastPort *rp, struct Rectangle *rect, struct Rectangle *r)
1167 struct gfx_driverdata *dd = ObtainDriverData(rp);
1169 if (dd && dd->dd_ClipRectangleFlags & RPCRF_VALID)
1171 *r = dd->dd_ClipRectangle;
1173 if (dd->dd_ClipRectangleFlags & RPCRF_RELRIGHT)
1175 r->MaxX += rect->MaxX - rect->MinX;
1178 if (dd->dd_ClipRectangleFlags & RPCRF_RELBOTTOM)
1180 r->MaxY += rect->MaxY - rect->MinY;
1183 r->MinX += rect->MinX;
1184 r->MinY += rect->MinY;
1185 r->MaxX += rect->MinX;
1186 r->MaxY += rect->MinY;
1188 return TRUE;
1191 return FALSE;
1194 /****************************************************************************************/
1196 BOOL GetRPClipRectangleForBitMap(struct RastPort *rp, struct BitMap *bm,
1197 struct Rectangle *r, struct GfxBase *GfxBase)
1199 struct Rectangle bm_rect;
1200 BOOL res;
1202 bm_rect.MinX = 0;
1203 bm_rect.MinY = 0;
1204 bm_rect.MaxX = GetBitMapAttr(bm, BMA_WIDTH) - 1;
1205 bm_rect.MaxY = GetBitMapAttr(bm, BMA_HEIGHT) - 1;
1207 res = GetRPClipRectangleForRect(rp, &bm_rect, r);
1209 #if BITMAP_CLIPPING
1210 if (!res)
1213 * Set the rectangle to total bitmap size. This prevents trashing memory
1214 * by hitting unallocated memory in HIDDs. They don't check bitmap bounds.
1216 *r = bm_rect;
1217 res = TRUE;
1219 #endif
1221 return res;