1d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//
3d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Licensed under the Apache License, Version 2.0 (the "License");
4d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// you may not use this file except in compliance with the License.
5d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// You may obtain a copy of the License at
6d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//
7d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//    http://www.apache.org/licenses/LICENSE-2.0
8d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//
9d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Unless required by applicable law or agreed to in writing, software
10d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// distributed under the License is distributed on an "AS IS" BASIS,
11d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// See the License for the specific language governing permissions and
13d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// limitations under the License.
14d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
15d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Device.hpp"
16d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
17d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "common/Image.hpp"
18d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Texture.h"
19d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
20d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Renderer/Renderer.hpp"
21d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Renderer/Clipper.hpp"
22d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Shader/PixelShader.hpp"
23d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Shader/VertexShader.hpp"
24d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Main/Config.hpp"
25d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Main/FrameBuffer.hpp"
26d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Common/Math.hpp"
27d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Common/Configurator.hpp"
28d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Common/Timer.hpp"
29d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "../common/debug.h"
30d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
31d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensnamespace es1
32d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{
33d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	using namespace sw;
34d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
35d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
36d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
37d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		renderTarget = nullptr;
38d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		depthBuffer = nullptr;
39d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		stencilBuffer = nullptr;
40d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
41d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setDepthBufferEnable(true);
42d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setFillMode(FILL_SOLID);
43d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setShadingMode(SHADING_GOURAUD);
44d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setDepthWriteEnable(true);
45d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setAlphaTestEnable(false);
46d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setSourceBlendFactor(BLEND_ONE);
47d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setDestBlendFactor(BLEND_ZERO);
48d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setCullMode(CULL_COUNTERCLOCKWISE);
49d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setDepthCompare(DEPTH_LESSEQUAL);
50d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setAlphaReference(0.0f);
51d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setAlphaCompare(ALPHA_ALWAYS);
52d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setAlphaBlendEnable(false);
53d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setFogEnable(false);
54d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setSpecularEnable(true);
55d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setLocalViewer(false);
56d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setFogColor(0);
57d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setPixelFogMode(FOG_NONE);
58d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setFogStart(0.0f);
59d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setFogEnd(1.0f);
60d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setFogDensity(1.0f);
61d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setRangeFogEnable(false);
62d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilEnable(false);
63d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilFailOperation(OPERATION_KEEP);
64d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilZFailOperation(OPERATION_KEEP);
65d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilPassOperation(OPERATION_KEEP);
66d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilCompare(STENCIL_ALWAYS);
67d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilReference(0);
68d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilMask(0xFFFFFFFF);
69d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilWriteMask(0xFFFFFFFF);
70d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setVertexFogMode(FOG_NONE);
71d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setClipFlags(0);
72d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setPointSize(1.0f);
73d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setPointSizeMin(0.125f);
74d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens        setPointSizeMax(8192.0f);
75d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setColorWriteMask(0, 0x0000000F);
76d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setBlendOperation(BLENDOP_ADD);
77d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		scissorEnable = false;
78d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setSlopeDepthBias(0.0f);
79d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setTwoSidedStencil(false);
80d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilFailOperationCCW(OPERATION_KEEP);
81d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilZFailOperationCCW(OPERATION_KEEP);
82d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilPassOperationCCW(OPERATION_KEEP);
83d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setStencilCompareCCW(STENCIL_ALWAYS);
84d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setColorWriteMask(1, 0x0000000F);
85d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setColorWriteMask(2, 0x0000000F);
86d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setColorWriteMask(3, 0x0000000F);
87d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setBlendConstant(0xFFFFFFFF);
88d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setWriteSRGB(false);
89d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setDepthBias(0.0f);
90d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setSeparateAlphaBlendEnable(false);
91d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setSourceBlendFactorAlpha(BLEND_ONE);
92d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setDestBlendFactorAlpha(BLEND_ZERO);
93d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setBlendOperationAlpha(BLENDOP_ADD);
94d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setPointSpriteEnable(true);
95d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
96d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		for(int i = 0; i < 16; i++)
97d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
98d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
99d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
100d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
101d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
102d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
103d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
104d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
105d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
106d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
107d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		for(int i = 0; i < 4; i++)
108d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
109d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
110d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
111d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
112d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
113d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
114d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
115d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
116d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
117d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
118d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		for(int i = 0; i < 6; i++)
119d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
120d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			float plane[4] = {0, 0, 0, 0};
121d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
122d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setClipPlane(i, plane);
123d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
124d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
125d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
126d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	Device::~Device()
127d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
128d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(renderTarget)
129d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
130d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			renderTarget->release();
131d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			renderTarget = nullptr;
132d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
133d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
134d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(depthBuffer)
135d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
136d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			depthBuffer->release();
137d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			depthBuffer = nullptr;
138d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
139d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
140d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(stencilBuffer)
141d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
142d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			stencilBuffer->release();
143d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			stencilBuffer = nullptr;
144d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
145d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
146d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		delete context;
147d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
148d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
149d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
150d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
151d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!renderTarget || !rgbaMask)
152d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
153d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return;
154d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
155d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
156d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		float rgba[4];
157d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		rgba[0] = red;
158d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		rgba[1] = green;
159d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		rgba[2] = blue;
160d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		rgba[3] = alpha;
161d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
162d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		sw::SliceRect clearRect = renderTarget->getRect();
163d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
164d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(scissorEnable)
165d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
166d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
167d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
168d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
169d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask);
170d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
171d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
172d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::clearDepth(float z)
173d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
174d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!depthBuffer)
175d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
176d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return;
177d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
178d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
179d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		z = clamp01(z);
180d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		sw::SliceRect clearRect = depthBuffer->getRect();
181d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
182d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(scissorEnable)
183d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
184d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
185d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
186d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
187d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
188d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
189d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
190d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::clearStencil(unsigned int stencil, unsigned int mask)
191d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
192d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!stencilBuffer)
193d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
194d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return;
195d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
196d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
197d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		sw::SliceRect clearRect = stencilBuffer->getRect();
198d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
199d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(scissorEnable)
200d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
201d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
202d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
203d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
204d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
205d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
206d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
207d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
208d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
209d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(height > OUTLINE_RESOLUTION)
210d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
211d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			ERR("Invalid parameters: %dx%d", width, height);
212d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return nullptr;
213d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
214d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
215d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		bool lockable = true;
216d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
217d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		switch(format)
218d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
219d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	//	case FORMAT_D15S1:
220d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FORMAT_D24S8:
221d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FORMAT_D24X8:
222d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	//	case FORMAT_D24X4S4:
223d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FORMAT_D24FS8:
224d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FORMAT_D32:
225d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FORMAT_D16:
226d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			lockable = false;
227d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
228d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	//	case FORMAT_S8_LOCKABLE:
229d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	//	case FORMAT_D16_LOCKABLE:
230d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FORMAT_D32F_LOCKABLE:
231d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	//	case FORMAT_D32_LOCKABLE:
232d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FORMAT_DF24S8:
233d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case FORMAT_DF16S8:
234d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			lockable = true;
235d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			break;
236d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		default:
237d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			UNREACHABLE(format);
238d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
239d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
240d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
241d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
242d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!surface)
243d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
244d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			ERR("Out of memory");
245d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return nullptr;
246d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
247d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
248d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return surface;
249d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
250d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
251d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
252d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
253d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(height > OUTLINE_RESOLUTION)
254d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
255d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			ERR("Invalid parameters: %dx%d", width, height);
256d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return nullptr;
257d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
258d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
259d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
260d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
261d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!surface)
262d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
263d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			ERR("Out of memory");
264d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return nullptr;
265d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
266d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
267d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return surface;
268d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
269d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
270d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount)
271d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
272d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!bindResources() || !primitiveCount)
273d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
274d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return;
275d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
276d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
277d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		draw(type, indexOffset, primitiveCount);
278d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
279d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
280d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount)
281d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
282d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!bindResources() || !primitiveCount)
283d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
284d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return;
285d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
286d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
287d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		setIndexBuffer(nullptr);
288d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
289d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		draw(type, 0, primitiveCount);
290d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
291d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
292d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::setScissorEnable(bool enable)
293d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
294d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		scissorEnable = enable;
295d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
296d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
297d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::setRenderTarget(int index, egl::Image *renderTarget)
298d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
299d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(renderTarget)
300d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
301d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			renderTarget->addRef();
302d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
303d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
304d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(this->renderTarget)
305d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
306d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			this->renderTarget->release();
307d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
308d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
309d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		this->renderTarget = renderTarget;
310d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
311d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		Renderer::setRenderTarget(index, renderTarget);
312d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
313d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
314d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::setDepthBuffer(egl::Image *depthBuffer)
315d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
316d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(this->depthBuffer == depthBuffer)
317d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
318d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return;
319d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
320d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
321d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(depthBuffer)
322d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
323d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			depthBuffer->addRef();
324d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
325d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
326d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(this->depthBuffer)
327d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
328d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			this->depthBuffer->release();
329d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
330d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
331d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		this->depthBuffer = depthBuffer;
332d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
333d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		Renderer::setDepthBuffer(depthBuffer);
334d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
335d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
336d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::setStencilBuffer(egl::Image *stencilBuffer)
337d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
338d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(this->stencilBuffer == stencilBuffer)
339d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
340d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return;
341d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
342d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
343d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(stencilBuffer)
344d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
345d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			stencilBuffer->addRef();
346d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
347d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
348d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(this->stencilBuffer)
349d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
350d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			this->stencilBuffer->release();
351d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
352d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
353d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		this->stencilBuffer = stencilBuffer;
354d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
355d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		Renderer::setStencilBuffer(stencilBuffer);
356d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
357d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
358d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::setScissorRect(const sw::Rect &rect)
359d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
360d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		scissorRect = rect;
361d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
362d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
363d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::setViewport(const Viewport &viewport)
364d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
365d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		this->viewport = viewport;
366d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
367d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
368d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter)
369d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
370d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
371d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
372d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			ERR("Invalid parameters");
373d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return false;
374d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
375d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
376d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		int sWidth = source->getWidth();
377d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		int sHeight = source->getHeight();
378d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		int dWidth = dest->getWidth();
379d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		int dHeight = dest->getHeight();
380d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
381d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		SliceRect sRect;
382d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		SliceRect dRect;
383d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
384d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(sourceRect)
385d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
386d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			sRect = *sourceRect;
387d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
388d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		else
389d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
390d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			sRect.y0 = 0;
391d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			sRect.x0 = 0;
392d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			sRect.y1 = sHeight;
393d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			sRect.x1 = sWidth;
394d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
395d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
396d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(destRect)
397d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
398d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			dRect = *destRect;
399d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
400d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		else
401d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
402d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			dRect.y0 = 0;
403d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			dRect.x0 = 0;
404d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			dRect.y1 = dHeight;
405d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			dRect.x1 = dWidth;
406d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
407d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
408d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
409d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
410d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat());
411d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		bool alpha0xFF = false;
412d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
413d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
414d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
415d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
416d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			equalFormats = true;
417d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			alpha0xFF = true;
418d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
419d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
420d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
421d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
422d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if(source->hasDepth())
423d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
424d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC);
425d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC);
426d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
427d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				unsigned int width = source->getWidth();
428d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				unsigned int height = source->getHeight();
429d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				unsigned int pitch = source->getInternalPitchB();
430d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
431d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				for(unsigned int y = 0; y < height; y++)
432d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				{
433d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
434d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
435d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					sourceBuffer += pitch;
436d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					destBuffer += pitch;
437d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				}
438d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
439d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				source->unlockInternal();
440d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				dest->unlockInternal();
441d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
442d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
443d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if(source->hasStencil())
444d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
445d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC);
446d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC);
447d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
448d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				unsigned int width = source->getWidth();
449d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				unsigned int height = source->getHeight();
450d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				unsigned int pitch = source->getStencilPitchB();
451d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
452d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				for(unsigned int y = 0; y < height; y++)
453d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				{
454d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
455d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
456d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					sourceBuffer += pitch;
457d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					destBuffer += pitch;
458d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				}
459d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
460d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				source->unlockStencil();
461d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				dest->unlockStencil();
462d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
463d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
464d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		else if(!scaling && equalFormats)
465d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
466d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC);
467d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC);
468d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			unsigned int sourcePitch = source->getInternalPitchB();
469d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			unsigned int destPitch = dest->getInternalPitchB();
470d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
471d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			unsigned int width = dRect.x1 - dRect.x0;
472d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			unsigned int height = dRect.y1 - dRect.y0;
473d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat());
474d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
475d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			for(unsigned int y = 0; y < height; y++)
476d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
477d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				memcpy(destBytes, sourceBytes, bytes);
478d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
479d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				if(alpha0xFF)
480d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				{
481d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					for(unsigned int x = 0; x < width; x++)
482d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					{
483d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens						destBytes[4 * x + 3] = 0xFF;
484d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					}
485d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				}
486d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
487d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				sourceBytes += sourcePitch;
488d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				destBytes += destPitch;
489d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
490d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
491d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			source->unlockInternal();
492d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			dest->unlockInternal();
493d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
494d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		else
495d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
496d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			blit(source, sRect, dest, dRect, scaling && filter);
497d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
498d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
499d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return true;
500d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
501d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
502d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	bool Device::bindResources()
503d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
504d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!bindViewport())
505d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
506d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return false;   // Zero-area target region
507d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
508d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
509d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return true;
510d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
511d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
512d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	bool Device::bindViewport()
513d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
514d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(viewport.width <= 0 || viewport.height <= 0)
515d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
516d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return false;
517d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
518d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
519d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(scissorEnable)
520d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
521d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
522d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
523d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				return false;
524d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
525d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
526d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			sw::Rect scissor;
527d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			scissor.x0 = scissorRect.x0;
528d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			scissor.x1 = scissorRect.x1;
529d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			scissor.y0 = scissorRect.y0;
530d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			scissor.y1 = scissorRect.y1;
531d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
532d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setScissor(scissor);
533d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
534d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		else
535d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
536d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			sw::Rect scissor;
537d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			scissor.x0 = viewport.x0;
538d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			scissor.x1 = viewport.x0 + viewport.width;
539d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			scissor.y0 = viewport.y0;
540d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			scissor.y1 = viewport.y0 + viewport.height;
541d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
542d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if(renderTarget)
543d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
544d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.x0 = max(scissor.x0, 0);
545d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.x1 = min(scissor.x1, renderTarget->getWidth());
546d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.y0 = max(scissor.y0, 0);
547d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.y1 = min(scissor.y1, renderTarget->getHeight());
548d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
549d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
550d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if(depthBuffer)
551d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
552d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.x0 = max(scissor.x0, 0);
553d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.x1 = min(scissor.x1, depthBuffer->getWidth());
554d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.y0 = max(scissor.y0, 0);
555d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.y1 = min(scissor.y1, depthBuffer->getHeight());
556d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
557d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
558d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			if(stencilBuffer)
559d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			{
560d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.x0 = max(scissor.x0, 0);
561d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.x1 = min(scissor.x1, stencilBuffer->getWidth());
562d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.y0 = max(scissor.y0, 0);
563d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens				scissor.y1 = min(scissor.y1, stencilBuffer->getHeight());
564d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			}
565d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
566d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			setScissor(scissor);
567d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
568d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
569d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		sw::Viewport view;
570d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		view.x0 = (float)viewport.x0;
571d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		view.y0 = (float)viewport.y0;
572d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		view.width = (float)viewport.width;
573d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		view.height = (float)viewport.height;
574d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		view.minZ = viewport.minZ;
575d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		view.maxZ = viewport.maxZ;
576d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
577d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		Renderer::setViewport(view);
578d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
579d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return true;
580d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
581d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
582d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
583d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
584d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(!rect)
585d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
586d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return true;
587d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
588d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
589d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
590d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
591d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return false;
592d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
593d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
594d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(rect->x0 < 0 || rect->y0 < 0)
595d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
596d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return false;
597d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
598d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
599d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
600d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		{
601d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens			return false;
602d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		}
603d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
604d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		return true;
605d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
606d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
607d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	void Device::finish()
608d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	{
609d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		synchronize();
610d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens	}
611d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}
612