Visual Studio 2012 Support
[xy_vsfilter.git] / src / thirdparty / VirtualDub / Kasumi / source / blt.cpp
blob7a3fabea006cf1ad315c975859e53d2475fbfbe2
1 // VirtualDub - Video processing and capture application
2 // Graphics support library
3 // Copyright (C) 1998-2009 Avery Lee
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <stdafx.h>
20 #include <vector>
21 #include <malloc.h>
22 #include <vd2/system/memory.h>
23 #include <vd2/system/cpuaccel.h>
24 #include <vd2/system/vdstl.h>
25 #include <vd2/Kasumi/pixmap.h>
26 #include <vd2/Kasumi/pixmaputils.h>
27 #include <vd2/Kasumi/pixmapops.h>
29 using namespace nsVDPixmap;
31 namespace {
32 typedef void (*tpPalettedBlitter)(void *dst, ptrdiff_t dstpitch, const void *src, ptrdiff_t srcpitch, vdpixsize w, vdpixsize h, const void *pal);
33 typedef void (*tpChunkyBlitter)(void *dst, ptrdiff_t dstpitch, const void *src, ptrdiff_t srcpitch, vdpixsize w, vdpixsize h);
34 typedef void (*tpPlanarBlitter)(const VDPixmap& dst, const VDPixmap& src, vdpixsize w, vdpixsize h);
37 bool VDPixmapBltDirect(const VDPixmap& dst, const VDPixmap& src, vdpixsize w, vdpixsize h);
39 void VDPixmapBltDirectPalettedConversion(const VDPixmap& dst, const VDPixmap& src, vdpixsize w, vdpixsize h, tpPalettedBlitter pBlitter) {
40 uint8 palbytes[256 * 3];
42 int palsize;
44 switch(src.format) {
45 case kPixFormat_Pal1:
46 palsize = 2;
47 break;
48 case kPixFormat_Pal2:
49 palsize = 4;
50 break;
51 case kPixFormat_Pal4:
52 palsize = 16;
53 break;
54 case kPixFormat_Pal8:
55 palsize = 256;
56 break;
57 default:
58 VDNEVERHERE;
61 VDASSERT(src.palette);
63 VDPixmap srcpal = { (void *)src.palette, NULL, palsize, 1, 0, kPixFormat_XRGB8888 };
64 VDPixmap dstpal = { palbytes, NULL, palsize, 1, 0, dst.format };
66 VDVERIFY(VDPixmapBltDirect(dstpal, srcpal, palsize, 1));
68 pBlitter(dst.data, dst.pitch, src.data, src.pitch, w, h, palbytes);
71 tpVDPixBltTable VDPixmapGetBlitterTable() {
72 #if defined(_WIN32) && defined(_M_IX86)
73 static tpVDPixBltTable pBltTable;
75 if (CPUGetEnabledExtensions() & CPUF_SUPPORTS_MMX) {
76 return VDGetPixBltTableX86MMX();
77 } else {
78 return VDGetPixBltTableX86Scalar();
80 #else
81 static tpVDPixBltTable pBltTable = VDGetPixBltTableReference();
82 return pBltTable;
83 #endif
86 bool VDPixmapBltDirect(const VDPixmap& dst, const VDPixmap& src, vdpixsize w, vdpixsize h) {
87 if ((unsigned)src.format >= kPixFormat_Max_Standard) {
88 VDASSERT(false);
89 return false;
92 if ((unsigned)dst.format >= kPixFormat_Max_Standard) {
93 VDASSERT(false);
94 return false;
97 const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(src.format);
99 if (src.format == dst.format) {
100 int qw = w;
101 int qh = h;
103 if (srcinfo.qchunky) {
104 qw = (qw + srcinfo.qw - 1) / srcinfo.qw;
105 qh = -(-h >> srcinfo.qhbits);
108 const int auxw = -(-w >> srcinfo.auxwbits);
109 const int auxh = -(-h >> srcinfo.auxhbits);
111 switch(srcinfo.auxbufs) {
112 case 2:
113 VDMemcpyRect(dst.data3, dst.pitch3, src.data3, src.pitch3, srcinfo.auxsize * auxw, auxh);
114 case 1:
115 VDMemcpyRect(dst.data2, dst.pitch2, src.data2, src.pitch2, srcinfo.auxsize * auxw, auxh);
116 case 0:
117 VDMemcpyRect(dst.data, dst.pitch, src.data, src.pitch, srcinfo.qsize * qw, qh);
120 return true;
123 VDPixmapBlitterFn pBlitter = VDPixmapGetBlitterTable()[src.format][dst.format];
125 if (!pBlitter)
126 return false;
128 pBlitter(dst, src, w, h);
129 return true;
132 bool VDPixmapIsBltPossible(int dst_format, int src_format) {
133 if (src_format == dst_format)
134 return true;
136 tpVDPixBltTable tab(VDPixmapGetBlitterTable());
138 if (tab[src_format][dst_format])
139 return true;
141 const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(src_format);
142 const VDPixmapFormatInfo& dstinfo = VDPixmapGetInfo(dst_format);
144 if (srcinfo.auxbufs > 0 || dstinfo.auxbufs > 0)
145 return false; // fail, planar buffers involved (can't do scanlines independently)
147 return (tab[src_format][kPixFormat_YUV444_XVYU] && tab[kPixFormat_YUV444_XVYU][dst_format])
148 ||(tab[src_format][kPixFormat_XRGB8888] && tab[kPixFormat_XRGB8888][dst_format]);
151 bool VDNOINLINE VDPixmapBltTwoStage(const VDPixmap& dst, const VDPixmap& src, vdpixsize w, vdpixsize h) {
152 const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(src.format);
153 const VDPixmapFormatInfo& dstinfo = VDPixmapGetInfo(dst.format);
155 if (srcinfo.auxbufs > 0 || dstinfo.auxbufs > 0)
156 return false; // fail, planar buffers involved
158 if (srcinfo.qh > 1)
159 return false; // fail, vertically packed formats involved
161 if (srcinfo.palsize)
162 return false; // fail, paletted formats involved
164 // Allocate a 4xW buffer and try round-tripping through either
165 // RGB32 or XYVU.
166 vdblock<uint32> tempBuf;
168 tpVDPixBltTable tab(VDPixmapGetBlitterTable());
170 VDPixmap linesrc(src);
171 VDPixmap linedst(dst);
172 VDPixmap linetmp = {};
174 if (w < 1024) {
175 linetmp.data = alloca(sizeof(uint32) * w);
176 } else {
177 tempBuf.resize(w + 1);
178 linetmp.data = tempBuf.data();
180 linetmp.pitch = 0;
181 linetmp.format = kPixFormat_YUV444_XVYU;
182 linetmp.w = w;
183 linetmp.h = 1;
185 VDPixmapBlitterFn pb1 = tab[src.format][kPixFormat_YUV444_XVYU];
186 VDPixmapBlitterFn pb2 = tab[kPixFormat_YUV444_XVYU][dst.format];
187 if (!pb1 || !pb2) {
188 pb1 = tab[src.format][kPixFormat_XRGB8888];
189 pb2 = tab[kPixFormat_XRGB8888][dst.format];
190 if (!pb1 || !pb2)
191 return false;
193 linetmp.format = kPixFormat_XRGB8888;
196 do {
197 pb1(linetmp, linesrc, w, 1);
198 pb2(linedst, linetmp, w, 1);
199 vdptrstep(linesrc.data, linesrc.pitch);
200 vdptrstep(linedst.data, linedst.pitch);
201 } while(--h);
202 return true;
205 bool VDPixmapBltFast(const VDPixmap& dst, const VDPixmap& src, vdpixsize w, vdpixsize h) {
206 if (w <= 0 || h <= 0) {
207 VDASSERT((w|h) >= 0);
208 return true;
211 if (VDPixmapBltDirect(dst, src, w, h))
212 return true;
214 // Oro... let's see if we can do a two-stage conversion.
215 return VDPixmapBltTwoStage(dst, src, w, h);
218 bool VDPixmapBlt(const VDPixmap& dst, const VDPixmap& src) {
219 vdpixsize w = std::min<vdpixsize>(src.w, dst.w);
220 vdpixsize h = std::min<vdpixsize>(src.h, dst.h);
222 if (!w || !h)
223 return true;
225 return VDPixmapBltFast(dst, src, w, h);
228 bool VDPixmapBlt(const VDPixmap& dst, vdpixpos x1, vdpixpos y1, const VDPixmap& src, vdpixpos x2, vdpixpos y2, vdpixsize w, vdpixsize h) {
229 if (x1 < 0) {
230 x2 -= x1;
231 w -= x1;
232 x1 = 0;
235 if (y1 < 0) {
236 y2 -= y1;
237 h -= y1;
238 y1 = 0;
241 if (x2 < 0) {
242 x1 -= x2;
243 w -= x2;
244 x2 = 0;
247 if (y2 < 0) {
248 y1 -= y2;
249 h -= y2;
250 y2 = 0;
253 if (w > dst.w - x1)
254 w = dst.w - x1;
256 if (h > dst.h - y1)
257 h = dst.h - y1;
259 if (w > src.w - x2)
260 w = src.w - x2;
262 if (h > src.h - y2)
263 h = src.h - y2;
265 if (w>=0 && h >= 0) {
266 VDPixmap dst2(VDPixmapOffset(dst, x1, y1));
267 VDPixmap src2(VDPixmapOffset(src, x2, y2));
269 return VDPixmapBltFast(dst2, src2, w, h);
272 return true;
275 extern bool VDPixmapStretchBltNearest_reference(const VDPixmap& dst, sint32 x1, sint32 y1, sint32 x2, sint32 y2, const VDPixmap& src, sint32 u1, sint32 v1, sint32 u2, sint32 v2);
276 extern bool VDPixmapStretchBltBilinear_reference(const VDPixmap& dst, sint32 x1, sint32 y1, sint32 x2, sint32 y2, const VDPixmap& src, sint32 u1, sint32 v1, sint32 u2, sint32 v2);
278 bool VDPixmapStretchBltNearest(const VDPixmap& dst, const VDPixmap& src) {
279 return VDPixmapStretchBltNearest(dst, 0, 0, dst.w<<16, dst.h<<16, src, 0, 0, src.w<<16, src.h<<16);
282 bool VDPixmapStretchBltNearest(const VDPixmap& dst, sint32 x1, sint32 y1, sint32 x2, sint32 y2, const VDPixmap& src, sint32 u1, sint32 v1, sint32 u2, sint32 v2) {
283 return VDPixmapStretchBltNearest_reference(dst, x1, y1, x2, y2, src, u1, v1, u2, v2);
286 bool VDPixmapStretchBltBilinear(const VDPixmap& dst, const VDPixmap& src) {
287 return VDPixmapStretchBltBilinear(dst, 0, 0, dst.w<<16, dst.h<<16, src, 0, 0, src.w<<16, src.h<<16);
290 bool VDPixmapStretchBltBilinear(const VDPixmap& dst, sint32 x1, sint32 y1, sint32 x2, sint32 y2, const VDPixmap& src, sint32 u1, sint32 v1, sint32 u2, sint32 v2) {
291 return VDPixmapStretchBltBilinear_reference(dst, x1, y1, x2, y2, src, u1, v1, u2, v2);