1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "Image.hpp"
16
17#include "Texture.h"
18#include "utilities.h"
19#include "../common/debug.h"
20#include "Common/Thread.hpp"
21
22#define _GDI32_
23#include <windows.h>
24#include <GL/GL.h>
25#include <GL/glext.h>
26
27namespace gl
28{
29	static sw::Resource *getParentResource(Texture *texture)
30	{
31		if(texture)
32		{
33			return texture->getResource();
34		}
35
36		return nullptr;
37	}
38
39	Image::Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
40		: sw::Surface(getParentResource(parentTexture), width, height, 1, 0, 1, selectInternalFormat(format, type), true, true)
41		, parentTexture(parentTexture), width(width), height(height), format(format), type(type)
42		, internalFormat(selectInternalFormat(format, type)), multiSampleDepth(1)
43	{
44		referenceCount = 1;
45	}
46
47	Image::Image(Texture *parentTexture, GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable, bool renderTarget)
48		: sw::Surface(getParentResource(parentTexture), width, height, 1, 0, multiSampleDepth, internalFormat, lockable, renderTarget)
49		, parentTexture(parentTexture), width(width), height(height), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), internalFormat(internalFormat), multiSampleDepth(multiSampleDepth)
50	{
51		referenceCount = 1;
52	}
53
54	Image::~Image()
55	{
56		ASSERT(referenceCount == 0);
57	}
58
59	void *Image::lock(unsigned int left, unsigned int top, sw::Lock lock)
60	{
61		return lockExternal(left, top, 0, lock, sw::PUBLIC);
62	}
63
64	unsigned int Image::getPitch() const
65	{
66		return getExternalPitchB();
67	}
68
69	void Image::unlock()
70	{
71		unlockExternal();
72	}
73
74	void *Image::lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client)
75	{
76		return Surface::lockInternal(x, y, z, lock, client);
77	}
78
79	void Image::unlockInternal()
80	{
81		Surface::unlockInternal();
82	}
83
84	int Image::getWidth()
85	{
86		return width;
87	}
88
89	int Image::getHeight()
90	{
91		return height;
92	}
93
94	GLenum Image::getFormat()
95	{
96		return format;
97	}
98
99	GLenum Image::getType()
100	{
101		return type;
102	}
103
104	sw::Format Image::getInternalFormat()
105	{
106		return internalFormat;
107	}
108
109	int Image::getMultiSampleDepth()
110	{
111		return multiSampleDepth;
112	}
113
114	void Image::addRef()
115	{
116		if(parentTexture)
117		{
118			return parentTexture->addRef();
119		}
120
121		sw::atomicIncrement(&referenceCount);
122	}
123
124	void Image::release()
125	{
126		if(parentTexture)
127		{
128			return parentTexture->release();
129		}
130
131		if(referenceCount > 0)
132		{
133			sw::atomicDecrement(&referenceCount);
134		}
135
136		if(referenceCount == 0)
137		{
138			delete this;
139		}
140	}
141
142	void Image::unbind()
143	{
144		parentTexture = nullptr;
145
146		release();
147	}
148
149	sw::Format Image::selectInternalFormat(GLenum format, GLenum type)
150	{
151		if(type == GL_NONE && format == GL_NONE)
152		{
153			return sw::FORMAT_NULL;
154		}
155		else if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
156		        format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
157		{
158			return sw::FORMAT_DXT1;
159		}
160		else if(format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)
161		{
162			return sw::FORMAT_DXT3;
163		}
164		else if(format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
165		{
166			return sw::FORMAT_DXT5;
167		}
168		else if(type == GL_FLOAT)
169		{
170			return sw::FORMAT_A32B32G32R32F;
171		}
172		else if(type == GL_HALF_FLOAT)
173		{
174			return sw::FORMAT_A16B16G16R16F;
175		}
176		else if(type == GL_UNSIGNED_BYTE)
177		{
178			if(format == GL_LUMINANCE)
179			{
180				return sw::FORMAT_L8;
181			}
182			else if(format == GL_LUMINANCE_ALPHA)
183			{
184				return sw::FORMAT_A8L8;
185			}
186			else if(format == GL_RGBA || format == GL_BGRA_EXT)
187			{
188				return sw::FORMAT_A8R8G8B8;
189			}
190			else if(format == GL_RGB)
191			{
192				return sw::FORMAT_X8R8G8B8;
193			}
194			else if(format == GL_ALPHA)
195			{
196				return sw::FORMAT_A8;
197			}
198			else UNREACHABLE(format);
199		}
200		else if(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT)
201		{
202			if(format == GL_DEPTH_COMPONENT)
203			{
204				return sw::FORMAT_D32FS8_TEXTURE;
205			}
206			else UNREACHABLE(format);
207		}
208		else if(type == GL_UNSIGNED_INT_24_8_EXT)
209		{
210			if(format == GL_DEPTH_STENCIL_EXT)
211			{
212				return sw::FORMAT_D32FS8_TEXTURE;
213			}
214			else UNREACHABLE(format);
215		}
216		else if(type == GL_UNSIGNED_SHORT_4_4_4_4)
217		{
218			return sw::FORMAT_A8R8G8B8;
219		}
220		else if(type == GL_UNSIGNED_SHORT_5_5_5_1)
221		{
222			return sw::FORMAT_A8R8G8B8;
223		}
224		else if(type == GL_UNSIGNED_SHORT_5_6_5)
225		{
226			return sw::FORMAT_R5G6B5;
227		}
228		else if(type == GL_UNSIGNED_INT_8_8_8_8_REV)
229		{
230			return sw::FORMAT_A8R8G8B8;
231		}
232
233		else UNREACHABLE(type);
234
235		return sw::FORMAT_A8R8G8B8;
236	}
237
238	void Image::loadImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLint unpackAlignment, const void *input)
239	{
240		GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment);
241		void *buffer = lock(0, 0, sw::LOCK_WRITEONLY);
242
243		if(buffer)
244		{
245			switch(type)
246			{
247			case GL_UNSIGNED_BYTE:
248			case GL_UNSIGNED_INT_8_8_8_8_REV:
249				switch(format)
250				{
251				case GL_ALPHA:
252					loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
253					break;
254				case GL_LUMINANCE:
255					loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
256					break;
257				case GL_LUMINANCE_ALPHA:
258					loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
259					break;
260				case GL_RGB:
261					loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
262					break;
263				case GL_RGBA:
264					loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
265					break;
266				case GL_BGRA_EXT:
267					loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
268					break;
269				default: UNREACHABLE(format);
270				}
271				break;
272			case GL_UNSIGNED_SHORT_5_6_5:
273				switch(format)
274				{
275				case GL_RGB:
276					loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
277					break;
278				default: UNREACHABLE(format);
279				}
280				break;
281			case GL_UNSIGNED_SHORT_4_4_4_4:
282				switch(format)
283				{
284				case GL_RGBA:
285					loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
286					break;
287				default: UNREACHABLE(format);
288				}
289				break;
290			case GL_UNSIGNED_SHORT_5_5_5_1:
291				switch(format)
292				{
293				case GL_RGBA:
294					loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
295					break;
296				default: UNREACHABLE(format);
297				}
298				break;
299			case GL_FLOAT:
300				switch(format)
301				{
302				// float textures are converted to RGBA, not BGRA
303				case GL_ALPHA:
304					loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
305					break;
306				case GL_LUMINANCE:
307					loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
308					break;
309				case GL_LUMINANCE_ALPHA:
310					loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
311					break;
312				case GL_RGB:
313					loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
314					break;
315				case GL_RGBA:
316					loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
317					break;
318				default: UNREACHABLE(format);
319				}
320				break;
321			case GL_HALF_FLOAT:
322				switch(format)
323				{
324				// float textures are converted to RGBA, not BGRA
325				case GL_ALPHA:
326					loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
327					break;
328				case GL_LUMINANCE:
329					loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
330					break;
331				case GL_LUMINANCE_ALPHA:
332					loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
333					break;
334				case GL_RGB:
335					loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
336					break;
337				case GL_RGBA:
338					loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
339					break;
340				default: UNREACHABLE(format);
341				}
342				break;
343			case GL_UNSIGNED_SHORT:
344				loadD16ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
345				break;
346			case GL_UNSIGNED_INT:
347				loadD32ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
348				break;
349			case GL_UNSIGNED_INT_24_8_EXT:
350				loadD24S8ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
351				break;
352			default: UNREACHABLE(type);
353			}
354		}
355
356		unlock();
357	}
358
359	void Image::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
360	{
361		for(int y = 0; y < height; y++)
362		{
363			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
364			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset;
365
366			memcpy(dest, source, width);
367		}
368	}
369
370	void Image::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
371	{
372		for(int y = 0; y < height; y++)
373		{
374			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
375			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
376
377			for(int x = 0; x < width; x++)
378			{
379				dest[4 * x + 0] = 0;
380				dest[4 * x + 1] = 0;
381				dest[4 * x + 2] = 0;
382				dest[4 * x + 3] = source[x];
383			}
384		}
385	}
386
387	void Image::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
388	{
389		for(int y = 0; y < height; y++)
390		{
391			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
392			unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8);
393
394			for(int x = 0; x < width; x++)
395			{
396				dest[4 * x + 0] = 0;
397				dest[4 * x + 1] = 0;
398				dest[4 * x + 2] = 0;
399				dest[4 * x + 3] = source[x];
400			}
401		}
402	}
403
404	void Image::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
405	{
406		for(int y = 0; y < height; y++)
407		{
408			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
409			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset;
410
411			memcpy(dest, source, width);
412		}
413	}
414
415	void Image::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
416	{
417		for(int y = 0; y < height; y++)
418		{
419			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
420			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
421
422			for(int x = 0; x < width; x++)
423			{
424				dest[4 * x + 0] = source[x];
425				dest[4 * x + 1] = source[x];
426				dest[4 * x + 2] = source[x];
427				dest[4 * x + 3] = 1.0f;
428			}
429		}
430	}
431
432	void Image::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
433	{
434		for(int y = 0; y < height; y++)
435		{
436			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
437			unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8);
438
439			for(int x = 0; x < width; x++)
440			{
441				dest[4 * x + 0] = source[x];
442				dest[4 * x + 1] = source[x];
443				dest[4 * x + 2] = source[x];
444				dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
445			}
446		}
447	}
448
449	void Image::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
450	{
451		for(int y = 0; y < height; y++)
452		{
453			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
454			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 2;
455
456			memcpy(dest, source, width * 2);
457		}
458	}
459
460	void Image::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
461	{
462		for(int y = 0; y < height; y++)
463		{
464			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
465			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
466
467			for(int x = 0; x < width; x++)
468			{
469				dest[4 * x + 0] = source[2*x+0];
470				dest[4 * x + 1] = source[2*x+0];
471				dest[4 * x + 2] = source[2*x+0];
472				dest[4 * x + 3] = source[2*x+1];
473			}
474		}
475	}
476
477	void Image::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
478	{
479		for(int y = 0; y < height; y++)
480		{
481			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
482			unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8);
483
484			for(int x = 0; x < width; x++)
485			{
486				dest[4 * x + 0] = source[2*x+0];
487				dest[4 * x + 1] = source[2*x+0];
488				dest[4 * x + 2] = source[2*x+0];
489				dest[4 * x + 3] = source[2*x+1];
490			}
491		}
492	}
493
494	void Image::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
495	{
496		for(int y = 0; y < height; y++)
497		{
498			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
499			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
500
501			for(int x = 0; x < width; x++)
502			{
503				dest[4 * x + 0] = source[x * 3 + 2];
504				dest[4 * x + 1] = source[x * 3 + 1];
505				dest[4 * x + 2] = source[x * 3 + 0];
506				dest[4 * x + 3] = 0xFF;
507			}
508		}
509	}
510
511	void Image::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
512	{
513		for(int y = 0; y < height; y++)
514		{
515			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
516			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 2;
517
518			memcpy(dest, source, width * 2);
519		}
520	}
521
522	void Image::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
523	{
524		for(int y = 0; y < height; y++)
525		{
526			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
527			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
528
529			for(int x = 0; x < width; x++)
530			{
531				dest[4 * x + 0] = source[x * 3 + 0];
532				dest[4 * x + 1] = source[x * 3 + 1];
533				dest[4 * x + 2] = source[x * 3 + 2];
534				dest[4 * x + 3] = 1.0f;
535			}
536		}
537	}
538
539	void Image::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
540	{
541		for(int y = 0; y < height; y++)
542		{
543			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
544			unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8);
545
546			for(int x = 0; x < width; x++)
547			{
548				dest[4 * x + 0] = source[x * 3 + 0];
549				dest[4 * x + 1] = source[x * 3 + 1];
550				dest[4 * x + 2] = source[x * 3 + 2];
551				dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
552			}
553		}
554	}
555
556	void Image::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
557	{
558		for(int y = 0; y < height; y++)
559		{
560			const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
561			unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4);
562
563			for(int x = 0; x < width; x++)
564			{
565				unsigned int rgba = source[x];
566				dest[x] = (rgba & 0xFF00FF00) | ((rgba << 16) & 0x00FF0000) | ((rgba >> 16) & 0x000000FF);
567			}
568		}
569	}
570
571	void Image::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
572	{
573		for(int y = 0; y < height; y++)
574		{
575			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
576			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
577
578			for(int x = 0; x < width; x++)
579			{
580				unsigned short rgba = source[x];
581				dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
582				dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
583				dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
584				dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
585			}
586		}
587	}
588
589	void Image::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
590	{
591		for(int y = 0; y < height; y++)
592		{
593			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
594			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
595
596			for(int x = 0; x < width; x++)
597			{
598				unsigned short rgba = source[x];
599				dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
600				dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
601				dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
602				dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
603			}
604		}
605	}
606
607	void Image::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
608	{
609		for(int y = 0; y < height; y++)
610		{
611			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
612			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
613
614			memcpy(dest, source, width * 16);
615		}
616	}
617
618	void Image::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
619	{
620		for(int y = 0; y < height; y++)
621		{
622			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
623			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8;
624
625			memcpy(dest, source, width * 8);
626		}
627	}
628
629	void Image::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
630	{
631		for(int y = 0; y < height; y++)
632		{
633			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
634			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
635
636			memcpy(dest, source, width*4);
637		}
638	}
639
640	void Image::loadD16ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
641	{
642		for(int y = 0; y < height; y++)
643		{
644			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
645			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4);
646
647			for(int x = 0; x < width; x++)
648			{
649				dest[x] = (float)source[x] / 0xFFFF;
650			}
651		}
652	}
653
654	void Image::loadD32ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
655	{
656		for(int y = 0; y < height; y++)
657		{
658			const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
659			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4);
660
661			for(int x = 0; x < width; x++)
662			{
663				dest[x] = (float)source[x] / 0xFFFFFFFF;
664			}
665		}
666	}
667
668	void Image::loadD24S8ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer)
669	{
670		for(int y = 0; y < height; y++)
671		{
672			const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
673			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4);
674
675			for(int x = 0; x < width; x++)
676			{
677				dest[x] = (float)(source[x] & 0xFFFFFF00) / 0xFFFFFF00;
678			}
679		}
680
681		unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, 0, 0, sw::PUBLIC));
682
683		if(stencil)
684		{
685			for(int y = 0; y < height; y++)
686			{
687				const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
688				unsigned char *dest = static_cast<unsigned char*>(stencil) + (y + yoffset) * getStencilPitchB() + xoffset;
689
690				for(int x = 0; x < width; x++)
691				{
692					dest[x] = static_cast<unsigned char>(source[x] & 0x000000FF);   // FIXME: Quad layout
693				}
694			}
695
696			unlockStencil();
697		}
698	}
699
700	void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
701	{
702		int inputPitch = ComputeCompressedPitch(width, format);
703		int rows = imageSize / inputPitch;
704		void *buffer = lock(xoffset, yoffset, sw::LOCK_WRITEONLY);
705
706		if(buffer)
707		{
708			for(int i = 0; i < rows; i++)
709			{
710				memcpy((void*)((GLbyte*)buffer + i * getPitch()), (void*)((GLbyte*)pixels + i * inputPitch), inputPitch);
711			}
712		}
713
714		unlock();
715	}
716}