1 // Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "IrrCompileConfig.h"
\r
6 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
8 #include "SoftwareDriver2_compile_config.h"
\r
9 #include "SoftwareDriver2_helper.h"
\r
10 #include "CSoftwareTexture2.h"
\r
11 #include "CSoftwareDriver2.h"
\r
20 //! stretches srcRect src to dstRect dst, applying a sliding window box filter in linear color space (sRGB->linear->sRGB)
\r
21 void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect<s32>* dstRect, const video::IImage* src, const core::rect<s32>* srcRect, size_t flags);
\r
23 //nearest pow of 2 ( 257 will be 256 not 512 )
\r
24 static inline core::dimension2d<u32> getOptimalSize(const core::dimension2d<u32>& original, const u32 allowNonPowerOfTwo, const u32 maxSize)
\r
27 if (allowNonPowerOfTwo)
\r
30 h = original.Height;
\r
35 while (w * 2 < original.Width) w *= 2;
\r
36 if (w * 2 - original.Width < original.Width - w) w *= 2;
\r
39 while (h * 2 < original.Height) h *= 2;
\r
40 if (h * 2 - original.Height < original.Height - h) h *= 2;
\r
42 if (maxSize && w > maxSize) w = maxSize;
\r
43 if (maxSize && h > maxSize) h = maxSize;
\r
44 return core::dimension2d<u32>(w, h);
\r
48 CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 flags, CBurningVideoDriver* driver)
\r
50 #if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
\r
54 , MipMapLOD(0), Flags(flags), Driver(driver)
\r
57 setDebugName("CSoftwareTexture2");
\r
60 #if SOFTWARE_DRIVER_2_MIPMAPPING_MAX <= 1
\r
61 Flags &= ~(GEN_MIPMAP | GEN_MIPMAP_AUTO);
\r
63 //set baseclass properties
\r
64 DriverType = EDT_BURNINGSVIDEO;
\r
65 ColorFormat = (Flags & IS_RENDERTARGET) ? SOFTWARE_DRIVER_2_RENDERTARGET_COLOR_FORMAT : SOFTWARE_DRIVER_2_TEXTURE_COLOR_FORMAT;
\r
66 IsRenderTarget = (Flags & IS_RENDERTARGET) != 0;
\r
67 HasMipMaps = (Flags & GEN_MIPMAP) != 0;
\r
68 MipMap0_Area[0] = 1;
\r
69 MipMap0_Area[1] = 1;
\r
71 for (size_t i = 0; i < array_size(MipMap); ++i) MipMap[i] = 0;
\r
74 OriginalSize = image->getDimension();
\r
75 OriginalColorFormat = image->getColorFormat();
\r
78 #if defined(IRRLICHT_sRGB)
\r
79 if (Flags & IMAGE_IS_LINEAR) image->set_sRGB(0);
\r
81 //guessing linear image
\r
82 if (name.find("light") >= 0 ||
\r
83 name.find("bump") >= 0 ||
\r
84 name.find("height") >= 0
\r
87 Flags |= TEXTURE_IS_LINEAR | IMAGE_IS_LINEAR;
\r
91 bool isCompressed = IImage::isCompressedFormat(OriginalColorFormat);
\r
94 os::Printer::log("Texture compression not available.", ELL_ERROR);
\r
97 //visual studio code warning
\r
98 u32 maxTexSize = SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE;
\r
100 #if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
\r
101 if (IsRenderTarget && name.find("RaceGUI::markers") >= 0)
\r
107 core::dimension2d<u32> optSize(OriginalSize.getOptimalSize(
\r
108 (Flags & ALLOW_NPOT) ? 0 : 1, // requirePowerOfTwo
\r
109 false, // requireSquare
\r
110 (Flags & ALLOW_NPOT) ? 1 : maxTexSize == SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE, // larger
\r
111 (Flags & ALLOW_NPOT) ? 0 : maxTexSize // maxValue
\r
115 core::dimension2d<u32> optSize(getOptimalSize(OriginalSize, Flags & ALLOW_NPOT, maxTexSize));
\r
116 if (OriginalSize == optSize)
\r
118 MipMap[0] = new CImage(ColorFormat, image->getDimension());
\r
119 #if defined(IRRLICHT_sRGB)
\r
120 MipMap[0]->set_sRGB((Flags & TEXTURE_IS_LINEAR) ? 0 : image->get_sRGB());
\r
122 if (!isCompressed && image->getData())
\r
123 image->copyTo(MipMap[0]);
\r
127 MipMap[0] = new CImage(ColorFormat, optSize);
\r
128 #if defined(IRRLICHT_sRGB)
\r
129 MipMap[0]->set_sRGB((Flags & TEXTURE_IS_LINEAR) ? 0 : image->get_sRGB());
\r
133 //image->copyToScalingBoxFilter ( MipMap[0],0, false );
\r
134 Resample_subSampling(BLITTER_TEXTURE, MipMap[0], 0, image, 0, Flags);
\r
136 // if Original Size is used for calculation ( 2D position, font) it will be wrong
\r
137 //OriginalSize = optSize;
\r
140 // Show Information about resizing
\r
141 if (OriginalSize != optSize ||
\r
142 ( OriginalColorFormat != ColorFormat &&
\r
143 !((OriginalColorFormat == ECF_R8G8B8 || OriginalColorFormat == ECF_A1R5G5B5) && ColorFormat == ECF_A8R8G8B8)
\r
148 core::stringw showName(name);
\r
149 snprintf_irr(buf, sizeof(buf), "Burningvideo: Texture '%ls' reformat %ux%u,%s -> %ux%u,%s",
\r
151 OriginalSize.Width, OriginalSize.Height, ColorFormatNames[OriginalColorFormat],
\r
152 optSize.Width, optSize.Height, ColorFormatNames[ColorFormat]
\r
154 os::Printer::log(buf, ELL_DEBUG);
\r
158 //select highest mipmap 0
\r
159 regenerateMipMapLevels(image->getMipMapsData());
\r
164 CSoftwareTexture2::~CSoftwareTexture2()
\r
166 for (size_t i = 0; i < array_size(MipMap); ++i)
\r
177 //! Regenerates the mip map levels of the texture. Useful after locking and
\r
178 //! modifying the texture
\r
179 #if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
\r
180 void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer)
\r
182 void CSoftwareTexture2::regenerateMipMapLevels(void* data)
\r
188 for (i = 1; i < array_size(MipMap); ++i)
\r
197 core::dimension2d<u32> newSize;
\r
199 if (HasMipMaps && ((Flags & GEN_MIPMAP_AUTO) || 0 == data))
\r
201 //need memory also if autogen mipmap disabled
\r
202 for (i = 1; i < array_size(MipMap); ++i)
\r
204 const core::dimension2du& upperDim = MipMap[i - 1]->getDimension();
\r
206 newSize.Width = core::s32_max(SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE, upperDim.Width >> 1);
\r
207 newSize.Height = core::s32_max(SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE, upperDim.Height >> 1);
\r
208 if (upperDim == newSize)
\r
211 MipMap[i] = new CImage(ColorFormat, newSize);
\r
212 #if defined(IRRLICHT_sRGB)
\r
213 MipMap[i]->set_sRGB(MipMap[i - 1]->get_sRGB());
\r
215 //MipMap[i]->fill ( 0xFFFF4040 );
\r
216 //MipMap[i-1]->copyToScalingBoxFilter( MipMap[i], 0, false );
\r
217 Resample_subSampling(BLITTER_TEXTURE, MipMap[i], 0, MipMap[0], 0, Flags);
\r
220 else if (HasMipMaps && data)
\r
222 //deactivated outside mipdata until TA knows how to handle this.
\r
224 //query mipmap dimension
\r
225 u8* mip_current = (u8*)data;
\r
226 const u8* mip_end = (u8*)data;
\r
228 core::dimension2d<u32> origSize = OriginalSize;
\r
232 if (origSize.Width > 1) origSize.Width >>= 1;
\r
233 if (origSize.Height > 1) origSize.Height >>= 1;
\r
234 mip_end += IImage::getDataSizeFromFormat(OriginalColorFormat, origSize.Width, origSize.Height);
\r
236 } while ((origSize.Width != 1 || origSize.Height != 1) && i < array_size(MipMap));
\r
238 //TODO: this is not true
\r
241 origSize = OriginalSize;
\r
242 for (i = 1; i < array_size(MipMap) && mip_current < mip_end; ++i)
\r
244 const core::dimension2du& upperDim = MipMap[i - 1]->getDimension();
\r
246 newSize.Width = core::s32_max(SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE, upperDim.Width >> 1);
\r
247 newSize.Height = core::s32_max(SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE, upperDim.Height >> 1);
\r
248 if (upperDim == newSize)
\r
251 if (origSize.Width > 1) origSize.Width >>= 1;
\r
252 if (origSize.Height > 1) origSize.Height >>= 1;
\r
254 if (OriginalColorFormat != ColorFormat)
\r
256 IImage* tmpImage = new CImage(OriginalColorFormat, origSize, mip_current, true, false);
\r
257 MipMap[i] = new CImage(ColorFormat, newSize);
\r
258 if (origSize == newSize)
\r
259 tmpImage->copyTo(MipMap[i]);
\r
261 tmpImage->copyToScalingBoxFilter(MipMap[i]);
\r
266 if (origSize == newSize)
\r
267 MipMap[i] = new CImage(ColorFormat, newSize, mip_current, false);
\r
270 MipMap[i] = new CImage(ColorFormat, newSize);
\r
271 IImage* tmpImage = new CImage(ColorFormat, origSize, mip_current, true, false);
\r
272 tmpImage->copyToScalingBoxFilter(MipMap[i]);
\r
276 mip_current += IImage::getDataSizeFromFormat(OriginalColorFormat, origSize.Width, origSize.Height);
\r
282 for (i = 1; i < 0 && i < array_size(MipMap); ++i)
\r
284 static u32 color[] = {
\r
286 0xFFFF0000,0xFF00FF00,0xFF0000FF,
\r
287 0xFFFFFF00,0xFF00FFFF,0xFFFF00FF,
\r
288 0xFFff6600,0xFF00ff66,0xFF6600FF,
\r
289 0xFF66ff00,0xFF0066ff,0xFFff0066,
\r
290 0xFF33ff00,0xFF0033ff,0xFF3300ff,
\r
291 0xFF0000FF,0xFF0000FF,0xFF0000FF
\r
297 const core::dimension2du& d = MipMap[i]->getDimension();
\r
298 core::rect<s32> p(0, 0, d.Width, d.Height);
\r
299 SColor c((color[i & 15] & 0x00FFFFFF) | 0xFF000000);
\r
301 core::rect<s32> dclip(border, border, d.Width - border, d.Height - border);
\r
303 Blit(BLITTER_TEXTURE_ALPHA_COLOR_BLEND, MipMap[i], &dclip, 0, MipMap[i], &p, c.color);
\r
307 //save mipmap chain
\r
311 const char* name = getName().getPath().c_str();
\r
317 if (name[i] == '/' || name[i] == '\\') filename = (s32)i + 1;
\r
318 //if (name[i] == '.') ext = i;
\r
321 for (i = 0; i < array_size(MipMap); ++i)
\r
325 snprintf_irr(buf, sizeof(buf), "mip/%s_%02d.png", name + filename, (s32)i);
\r
326 Driver->writeImageToFile(MipMap[i], buf);
\r
334 void CSoftwareTexture2::calcDerivative()
\r
336 //reset current MipMap
\r
340 const core::dimension2du& dim = MipMap[0]->getDimension();
\r
341 MipMap0_Area[0] = dim.Width;
\r
342 MipMap0_Area[1] = dim.Height; // screensize of a triangle
\r
344 //TA: try to mimic openGL mipmap. ( don't do this!)
\r
345 //if (MipMap0_Area[0] < 32) MipMap0_Area[0] = 32;
\r
346 //if (MipMap0_Area[1] < 32) MipMap0_Area[1] = 32;
\r
348 Size = dim; // MipMap[MipMapLOD]->getDimension();
\r
349 Pitch = MipMap[MipMapLOD]->getPitch();
\r
352 //preCalc mipmap texel center boundaries
\r
353 for (size_t i = 0; i < array_size(MipMap); ++i)
\r
355 CSoftwareTexture2_Bound& b = TexBound[i];
\r
358 const core::dimension2du& dim = MipMap[i]->getDimension();
\r
359 //f32 u = 1.f / dim.Width;
\r
360 //f32 v = 1.f / dim.Height;
\r
362 b.w = dim.Width - 1.f;
\r
363 b.h = dim.Height - 1.f;
\r
364 b.cx = 0.f; //u*0.005f;
\r
365 b.cy = 0.f; //v*0.005f;
\r
379 /* Software Render Target 2 */
\r
381 CSoftwareRenderTarget2::CSoftwareRenderTarget2(CBurningVideoDriver* driver) : Driver(driver)
\r
382 #if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
\r
386 DriverType = EDT_BURNINGSVIDEO;
\r
388 Texture.set_used(1);
\r
392 CSoftwareRenderTarget2::~CSoftwareRenderTarget2()
\r
395 Texture[0]->drop();
\r
398 void CSoftwareRenderTarget2::setTexture(const core::array<ITexture*>& texture, ITexture* depthStencil, const core::array<E_CUBE_SURFACE>& cubeSurfaces)
\r
400 if (Texture != texture)
\r
402 ITexture* prevTexture = Texture[0];
\r
404 bool textureDetected = false;
\r
406 for (u32 i = 0; i < texture.size(); ++i)
\r
408 if (texture[i] && texture[i]->getDriverType() == EDT_BURNINGSVIDEO)
\r
410 Texture[0] = texture[i];
\r
411 Texture[0]->grab();
\r
412 textureDetected = true;
\r
419 prevTexture->drop();
\r
421 if (!textureDetected)
\r
427 static const float srgb_8bit_to_linear_float[1 << 8] = {
\r
428 0.0f, 3.03527e-4f, 6.07054e-4f, 9.10581e-4f,
\r
429 0.001214108f, 0.001517635f, 0.001821162f, 0.0021246888f,
\r
430 0.002428216f, 0.002731743f, 0.00303527f, 0.0033465358f,
\r
431 0.0036765074f, 0.004024717f, 0.004391442f, 0.0047769537f,
\r
432 0.005181517f, 0.005605392f, 0.0060488335f, 0.006512091f,
\r
433 0.0069954107f, 0.007499032f, 0.008023193f, 0.008568126f,
\r
434 0.009134059f, 0.009721218f, 0.010329823f, 0.010960095f,
\r
435 0.011612245f, 0.012286489f, 0.0129830325f, 0.013702083f,
\r
436 0.014443845f, 0.015208516f, 0.015996294f, 0.016807377f,
\r
437 0.017641956f, 0.018500222f, 0.019382363f, 0.020288564f,
\r
438 0.021219011f, 0.022173885f, 0.023153368f, 0.024157634f,
\r
439 0.025186861f, 0.026241222f, 0.027320893f, 0.02842604f,
\r
440 0.029556835f, 0.030713445f, 0.031896032f, 0.033104766f,
\r
441 0.034339808f, 0.035601314f, 0.036889452f, 0.038204372f,
\r
442 0.039546236f, 0.0409152f, 0.04231141f, 0.04373503f,
\r
443 0.045186203f, 0.046665087f, 0.048171826f, 0.049706567f,
\r
444 0.051269464f, 0.05286065f, 0.05448028f, 0.056128494f,
\r
445 0.057805438f, 0.059511244f, 0.06124606f, 0.06301002f,
\r
446 0.06480327f, 0.066625945f, 0.068478175f, 0.0703601f,
\r
447 0.07227185f, 0.07421357f, 0.07618539f, 0.07818743f,
\r
448 0.08021983f, 0.082282715f, 0.084376216f, 0.086500466f,
\r
449 0.08865559f, 0.09084172f, 0.093058966f, 0.09530747f,
\r
450 0.097587354f, 0.09989873f, 0.10224174f, 0.10461649f,
\r
451 0.107023105f, 0.10946172f, 0.111932434f, 0.11443538f,
\r
452 0.11697067f, 0.119538434f, 0.122138776f, 0.12477182f,
\r
453 0.12743768f, 0.13013647f, 0.13286832f, 0.13563333f,
\r
454 0.13843162f, 0.14126329f, 0.14412847f, 0.14702727f,
\r
455 0.14995979f, 0.15292616f, 0.15592647f, 0.15896083f,
\r
456 0.16202939f, 0.1651322f, 0.1682694f, 0.17144111f,
\r
457 0.1746474f, 0.17788842f, 0.18116425f, 0.18447499f,
\r
458 0.18782078f, 0.19120169f, 0.19461784f, 0.19806932f,
\r
459 0.20155625f, 0.20507874f, 0.20863687f, 0.21223076f,
\r
460 0.21586053f, 0.21952623f, 0.22322798f, 0.2269659f,
\r
461 0.23074007f, 0.23455061f, 0.2383976f, 0.24228115f,
\r
462 0.24620135f, 0.2501583f, 0.25415212f, 0.25818288f,
\r
463 0.2622507f, 0.26635563f, 0.27049783f, 0.27467734f,
\r
464 0.2788943f, 0.28314877f, 0.28744087f, 0.29177067f,
\r
465 0.2961383f, 0.3005438f, 0.30498734f, 0.30946895f,
\r
466 0.31398875f, 0.3185468f, 0.32314324f, 0.32777813f,
\r
467 0.33245155f, 0.33716366f, 0.34191445f, 0.3467041f,
\r
468 0.35153264f, 0.35640016f, 0.36130682f, 0.36625263f,
\r
469 0.3712377f, 0.37626216f, 0.38132605f, 0.38642946f,
\r
470 0.3915725f, 0.39675525f, 0.4019778f, 0.40724024f,
\r
471 0.41254264f, 0.4178851f, 0.4232677f, 0.42869052f,
\r
472 0.43415368f, 0.4396572f, 0.44520122f, 0.45078582f,
\r
473 0.45641103f, 0.46207702f, 0.4677838f, 0.4735315f,
\r
474 0.4793202f, 0.48514995f, 0.4910209f, 0.496933f,
\r
475 0.5028865f, 0.50888133f, 0.5149177f, 0.5209956f,
\r
476 0.52711517f, 0.53327644f, 0.5394795f, 0.5457245f,
\r
477 0.55201143f, 0.55834043f, 0.5647115f, 0.57112485f,
\r
478 0.57758045f, 0.58407843f, 0.59061885f, 0.5972018f,
\r
479 0.60382736f, 0.61049557f, 0.6172066f, 0.62396044f,
\r
480 0.63075715f, 0.6375969f, 0.6444797f, 0.65140563f,
\r
481 0.65837485f, 0.66538733f, 0.67244315f, 0.6795425f,
\r
482 0.6866853f, 0.6938718f, 0.7011019f, 0.7083758f,
\r
483 0.71569353f, 0.7230551f, 0.73046076f, 0.73791045f,
\r
484 0.74540424f, 0.7529422f, 0.7605245f, 0.76815116f,
\r
485 0.7758222f, 0.7835378f, 0.791298f, 0.7991027f,
\r
486 0.8069523f, 0.8148466f, 0.82278574f, 0.8307699f,
\r
487 0.838799f, 0.8468732f, 0.8549926f, 0.8631572f,
\r
488 0.8713671f, 0.8796224f, 0.8879231f, 0.8962694f,
\r
489 0.9046612f, 0.91309863f, 0.92158186f, 0.9301109f,
\r
490 0.9386857f, 0.9473065f, 0.9559733f, 0.9646863f,
\r
491 0.9734453f, 0.9822506f, 0.9911021f, 1.0f,
\r
494 int linear_to_srgb_8bit(const float x) {
\r
495 if (x <= 0.f) return 0;
\r
496 if (x >= 1.f) return 255;
\r
497 const float *table = SRGB_8BIT_TO_LINEAR_FLOAT;
\r
499 for (int i = 128; i != 0; i >>= 1) {
\r
500 if (table[y + i] <= x)
\r
503 if (x - table[y] <= table[y + 1] - x)
\r
511 u32 linear_to_srgb_8bit(const float v)
\r
515 const size_t x = c.u;
\r
516 const u32* table = (u32*)srgb_8bit_to_linear_float;
\r
518 y += table[y + 128] <= x ? 128 : 0;
\r
519 y += table[y + 64] <= x ? 64 : 0;
\r
520 y += table[y + 32] <= x ? 32 : 0;
\r
521 y += table[y + 16] <= x ? 16 : 0;
\r
522 y += table[y + 8] <= x ? 8 : 0;
\r
523 y += table[y + 4] <= x ? 4 : 0;
\r
524 y += table[y + 2] <= x ? 2 : 0;
\r
525 y += table[y + 1] <= x ? 1 : 0;
\r
530 // 2D Region half open [x0;x1[
\r
539 static inline int clipTest(absrect2& o, const core::rect<s32>* a, const absrect2& b)
\r
550 o.x0 = core::s32_max(a->UpperLeftCorner.X, b.x0);
\r
551 o.x1 = core::s32_min(a->LowerRightCorner.X, b.x1);
\r
552 o.y0 = core::s32_max(a->UpperLeftCorner.Y, b.y0);
\r
553 o.y1 = core::s32_min(a->LowerRightCorner.Y, b.y1);
\r
556 clipTest |= o.x0 >= o.x1 ? 1 : 0;
\r
557 clipTest |= o.y0 >= o.y1 ? 2 : 0;
\r
561 //! stretches srcRect src to dstRect dst, applying a sliding window box filter in linear color space (sRGB->linear->sRGB)
\r
562 // todo: texture jumps (mip selection problem)
\r
563 void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect<s32>* dstRect,
\r
564 const video::IImage* src, const core::rect<s32>* srcRect, size_t flags)
\r
566 u8* dstData = (u8*)dst->getData();
\r
567 const absrect2 dst_clip = { 0,0,(s32)dst->getDimension().Width,(s32)dst->getDimension().Height };
\r
569 if (clipTest(dc, dstRect, dst_clip) || !dstData) return;
\r
570 const video::ECOLOR_FORMAT dstFormat = dst->getColorFormat();
\r
572 const u8* srcData = (u8*)src->getData();
\r
573 const absrect2 src_clip = { 0,0,(s32)src->getDimension().Width,(s32)src->getDimension().Height };
\r
575 if (clipTest(sc, srcRect, src_clip) || !srcData) return;
\r
576 const video::ECOLOR_FORMAT srcFormat = src->getColorFormat();
\r
578 #if defined(IRRLICHT_sRGB)
\r
579 const int dst_sRGB = dst->get_sRGB();
\r
580 const int src_sRGB = src->get_sRGB();
\r
582 const int dst_sRGB = (flags & CSoftwareTexture2::TEXTURE_IS_LINEAR) ? 0 : 1;
\r
583 const int src_sRGB = (flags & CSoftwareTexture2::IMAGE_IS_LINEAR) ? 0 : 1;
\r
589 scale[0] = (float)(sc.x1 - sc.x0) / (float)(dc.x1 - dc.x0);
\r
590 scale[1] = (float)(sc.y1 - sc.y0) / (float)(dc.y1 - dc.y0);
\r
591 const float rs = 1.f / (scale[0] * scale[1]);
\r
598 f[3] = (float)sc.y0;
\r
599 for (int dy = dc.y0; dy < dc.y1; ++dy)
\r
602 f[3] = sc.y0 + (dy + 1 - dc.y0) * scale[1];
\r
603 if (f[3] >= sc.y1) f[3] = sc.y1 - 0.001f; //todo:1.f/dim should be enough
\r
605 f[2] = (float)sc.x0;
\r
606 for (int dx = dc.x0; dx < dc.x1; ++dx)
\r
609 f[2] = sc.x0 + (dx + 1 - dc.x0) * scale[0];
\r
610 if (f[2] >= sc.x1) f[2] = sc.x1 - 0.001f;
\r
612 //accumulate linear color
\r
619 fi[0] = (int)(f[0]);
\r
620 fi[1] = (int)(f[1]);
\r
621 fi[2] = (int)(f[2]);
\r
622 fi[3] = (int)(f[3]);
\r
625 for (int fy = fi[1]; fy <= fi[3]; ++fy)
\r
628 if (fy == fi[1]) w[1] -= f[1] - fy;
\r
629 if (fy == fi[3]) w[1] -= fy + 1 - f[3];
\r
631 for (int fx = fi[0]; fx <= fi[2]; ++fx)
\r
634 if (fx == fi[0]) w[0] -= f[0] - fx;
\r
635 if (fx == fi[2]) w[0] -= fx + 1 - f[2];
\r
637 const float ws = w[1] * w[0] * rs;
\r
641 case video::ECF_A1R5G5B5: sbgra = video::A1R5G5B5toA8R8G8B8(*(u16*)(srcData + (fy * src_clip.x1) * 2 + (fx * 2))); break;
\r
642 case video::ECF_R5G6B5: sbgra = video::R5G6B5toA8R8G8B8(*(u16*)(srcData + (fy * src_clip.x1) * 2 + (fx * 2))); break;
\r
643 case video::ECF_A8R8G8B8: sbgra = *(u32*)(srcData + (fy * src_clip.x1) * 4 + (fx * 4)); break;
\r
644 case video::ECF_R8G8B8:
\r
646 const u8* p = srcData + (fy * src_clip.x1) * 3 + (fx * 3);
\r
647 sbgra = 0xFF000000 | p[0] << 16 | p[1] << 8 | p[2];
\r
653 sum[0] += srgb_8bit_to_linear_float[(sbgra) & 0xFF] * ws;
\r
654 sum[1] += srgb_8bit_to_linear_float[(sbgra >> 8) & 0xFF] * ws;
\r
655 sum[2] += srgb_8bit_to_linear_float[(sbgra >> 16) & 0xFF] * ws;
\r
656 sum[3] += ((sbgra >> 24) & 0xFF) * ws;
\r
660 sum[0] += ((sbgra) & 0xFF) * ws;
\r
661 sum[1] += ((sbgra >> 8) & 0xFF) * ws;
\r
662 sum[2] += ((sbgra >> 16) & 0xFF) * ws;
\r
663 sum[3] += ((sbgra >> 24) & 0xFF) * ws;
\r
670 case BLITTER_TEXTURE_ALPHA_BLEND:
\r
671 case BLITTER_TEXTURE_ALPHA_COLOR_BLEND:
\r
678 sbgra = linear_to_srgb_8bit(sum[0]) |
\r
679 linear_to_srgb_8bit(sum[1]) << 8 |
\r
680 linear_to_srgb_8bit(sum[2]) << 16 |
\r
681 (u32)(sum[3]) << 24;
\r
685 sbgra = (u32)(sum[0]) |
\r
686 (u32)(sum[1]) << 8 |
\r
687 (u32)(sum[2]) << 16 |
\r
688 (u32)(sum[3]) << 24;
\r
692 case video::ECF_A8R8G8B8: *(u32*)(dstData + (dy * dst_clip.x1) * 4 + (dx * 4)) = sbgra; break;
\r
693 case video::ECF_R8G8B8:
\r
695 u8* p = dstData + (dy * dst_clip.x1) * 3 + (dx * 3);
\r
696 p[2] = (sbgra) & 0xFF;
\r
697 p[1] = (sbgra >> 8) & 0xFF;
\r
698 p[0] = (sbgra >> 16) & 0xFF;
\r
700 case video::ECF_A1R5G5B5: *(u16*)(dstData + (dy * dst_clip.x1) * 2 + (dx * 2)) = video::A8R8G8B8toA1R5G5B5(sbgra); break;
\r
701 case video::ECF_R5G6B5: *(u16*)(dstData + (dy * dst_clip.x1) * 2 + (dx * 2)) = video::A8R8G8B8toR5G6B5(sbgra); break;
\r
710 } // end namespace video
\r
711 } // end namespace irr
\r
713 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r