revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / cgfx / scalepixelarray.c
blob8606dfb4b6425aee45d32b9252610e5fc08de3a7
1 /*
2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <hidd/gfx.h>
11 #include <proto/cybergraphics.h>
13 #include "cybergraphics_intern.h"
14 #include "gfxfuncsupport.h"
16 struct render_data
18 OOP_Object *srcbm_obj;
19 OOP_Object *gfx_hidd;
22 struct dest_box
24 UWORD x, y, w, h;
27 static ULONG RenderHook(struct render_data *data, LONG srcx, LONG srcy,
28 OOP_Object *dstbm_obj, OOP_Object *dst_gc, struct Rectangle *rect,
29 struct GfxBase *GfxBase);
31 /* Work around an m68k GCC issue, with AROS_LH10 macros.
33 * Due to the AROS_LH10() macro using so many data registers,
34 * we get a register spill during certain optimization levels.
36 * This 'hack' thunks the register call to a stack call, and passes
37 * the bounds using an address register, so that optimization has more
38 * data registers to play with.
40 * NB: It must have global scope (not 'static') so that it doesn't fold
41 * into the regcall routine. On non-regcall systems, this will, at worst,
42 * convert to a 'JMP internal_ScalePixelArray' with no stack manipulation.
44 LONG internal_ScalePixelArray(APTR srcRect, UWORD SrcW, UWORD SrcH,
45 UWORD SrcMod, struct RastPort *RastPort, struct dest_box *dest_bounds,
46 UBYTE SrcFormat, struct Library *CyberGfxBase);
48 /*****************************************************************************
50 NAME */
51 #include <proto/cybergraphics.h>
53 AROS_LH10(LONG, ScalePixelArray,
55 /* SYNOPSIS */
56 AROS_LHA(APTR , srcRect, A0),
57 AROS_LHA(UWORD , SrcW, D0),
58 AROS_LHA(UWORD , SrcH, D1),
59 AROS_LHA(UWORD , SrcMod, D2),
60 AROS_LHA(struct RastPort *, RastPort, A1),
61 AROS_LHA(UWORD , DestX, D3),
62 AROS_LHA(UWORD , DestY, D4),
63 AROS_LHA(UWORD , DestW, D5),
64 AROS_LHA(UWORD , DestH, D6),
65 AROS_LHA(UBYTE , SrcFormat, D7),
67 /* LOCATION */
68 struct Library *, CyberGfxBase, 15, Cybergraphics)
70 /* FUNCTION
71 Fills all or part of a RastPort with a rectangular block of raw pixel
72 values. The source pixels are scaled to fit the destination area, i.e.
73 some pixels may be duplicated or dropped according to the need to
74 stretch or compress the source block.
76 INPUTS
77 srcRect - pointer to the pixel values.
78 SrcW, SrcH - width and height of the source rectangle (in pixels).
79 SrcMod - the number of bytes in each row of the source rectangle.
80 RastPort - the RastPort to write to.
81 DestX, DestY - top-lefthand corner of portion of destination RastPort
82 to write to (in pixels).
83 DestW, DestH - size of the destination rectangle (in pixels).
84 SrcFormat - the format of the source pixels. See WritePixelArray for
85 possible values.
87 RESULT
88 count - the number of pixels written to.
90 NOTES
92 EXAMPLE
94 BUGS
96 SEE ALSO
97 WritePixelArray()
99 INTERNALS
101 *****************************************************************************/
103 AROS_LIBFUNC_INIT
105 struct dest_box dest_bounds;
107 dest_bounds.x = DestX;
108 dest_bounds.y = DestY;
109 dest_bounds.w = DestW;
110 dest_bounds.h = DestH;
112 return internal_ScalePixelArray(srcRect, SrcW, SrcH, SrcMod, RastPort,
113 &dest_bounds, SrcFormat, CyberGfxBase);
115 AROS_LIBFUNC_EXIT
118 LONG internal_ScalePixelArray(APTR srcRect, UWORD SrcW, UWORD SrcH,
119 UWORD SrcMod, struct RastPort *RastPort, struct dest_box *dest_bounds,
120 UBYTE SrcFormat, struct Library *CyberGfxBase)
122 ULONG result = 0;
123 struct render_data data;
124 struct Rectangle rr;
125 OOP_Object *gfx_hidd, *tempbm_obj, *tempbm2_obj, *gc;
126 struct BitScaleArgs scale_args = {0};
127 struct TagItem bm_tags[] =
129 {aHidd_BitMap_GfxHidd, 0},
130 {aHidd_BitMap_Width, SrcW},
131 {aHidd_BitMap_Height, SrcH},
132 {aHidd_BitMap_StdPixFmt, 0},
133 {TAG_END, 0}
135 struct TagItem gc_tags[] =
137 {aHidd_GC_DrawMode, vHidd_GC_DrawMode_Copy},
138 {TAG_DONE, 0UL}
141 D(bug("ScalePixelArray(%p, %d, %d, %d, %p, %d, %d, %d, %d, %d)\n",
142 srcRect, SrcW, SrcH, SrcMod, RastPort, dest_bounds->x, dest_bounds->y,
143 dest_bounds->w, dest_bounds->h, SrcFormat));
145 if (SrcW == 0 || SrcH == 0 || dest_bounds->w == 0 || dest_bounds->h == 0)
146 return 0;
148 /* This is AROS Cybergraphx - We only work wih Gfx Hidd bitmaps */
150 if (!IS_HIDD_BM(RastPort->BitMap))
152 D(bug("!!!!! Trying to use CGFX call on non-hidd bitmap in ScalePixelArray() !!!\n"));
153 return 0;
156 /* Query the bitmaps Gfx Hidd, and create a suitable GC Object (graphics context) */
158 OOP_GetAttr(HIDD_BM_OBJ(RastPort->BitMap), aHidd_BitMap_GfxHidd,
159 (IPTR *)&gfx_hidd);
160 gc = HIDD_Gfx_CreateObject(gfx_hidd, GetCGFXBase(CyberGfxBase)->basegc, gc_tags);
161 if (gc)
163 /* Create two temporary bitmap objects: one the size of the source area
164 and another the size of the destination area */
166 bm_tags[0].ti_Data = (IPTR)gfx_hidd;
167 bm_tags[3].ti_Data = GetHIDDRectFmt(SrcFormat, RastPort, CyberGfxBase);
168 tempbm_obj = HIDD_Gfx_CreateObject(gfx_hidd, GetCGFXBase(CyberGfxBase)->basebm, bm_tags);
169 if (tempbm_obj)
171 bm_tags[1].ti_Data = dest_bounds->w;
172 bm_tags[2].ti_Data = dest_bounds->h;
173 #if 0
174 // FIXME: This doesn't work (X11 and VESA). Should it?
175 bm_tags[3].ti_Tag = aHidd_BitMap_Friend;
176 bm_tags[3].ti_Data = (IPTR)HIDD_BM_OBJ(RastPort->BitMap);
177 #endif
178 tempbm2_obj = HIDD_Gfx_CreateObject(gfx_hidd, GetCGFXBase(CyberGfxBase)->basebm, bm_tags);
179 if (tempbm2_obj)
181 /* Copy the source array to its temporary bitmap object */
183 HIDD_BM_PutImage(tempbm_obj, gc, srcRect, SrcMod, 0, 0, SrcW, SrcH,
184 vHidd_StdPixFmt_Native);
186 /* Scale temporary source bitmap on to temporary destination bitmap */
188 scale_args.bsa_SrcWidth = SrcW;
189 scale_args.bsa_SrcHeight = SrcH;
190 scale_args.bsa_DestWidth = dest_bounds->w;
191 scale_args.bsa_DestHeight = dest_bounds->h;
192 HIDD_BM_BitMapScale(tempbm2_obj, tempbm_obj, tempbm2_obj, &scale_args,
193 gc);
195 /* Render temporary destination bitmap to destination bitmap */
197 data.srcbm_obj = tempbm2_obj;
198 data.gfx_hidd = gfx_hidd;
199 rr.MinX = dest_bounds->x;
200 rr.MinY = dest_bounds->y;
201 rr.MaxX = dest_bounds->x + dest_bounds->w - 1;
202 rr.MaxY = dest_bounds->y + dest_bounds->h - 1;
203 result = DoRenderFunc(RastPort, NULL, &rr, RenderHook, &data, TRUE);
205 /* Discard temporary resources */
207 OOP_DisposeObject(tempbm2_obj);
209 OOP_DisposeObject(tempbm_obj);
211 OOP_DisposeObject(gc);
214 return result;
215 } /* ScalePixelArray */
217 static ULONG RenderHook(struct render_data *data, LONG srcx, LONG srcy,
218 OOP_Object *dstbm_obj, OOP_Object *dst_gc, struct Rectangle *rect,
219 struct GfxBase *GfxBase)
221 ULONG width = rect->MaxX - rect->MinX + 1;
222 ULONG height = rect->MaxY - rect->MinY + 1;
224 HIDD_Gfx_CopyBox(data->gfx_hidd, data->srcbm_obj, srcx, srcy, dstbm_obj,
225 rect->MinX, rect->MinY, width, height, dst_gc);
227 return width * height;