blob: af091645966dc66e2f4ab2b16f03328d90d1865f [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// 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 "Device.hpp"
16
17#include "common/Image.hpp"
18#include "Texture.h"
19
20#include "Renderer/Renderer.hpp"
21#include "Renderer/Clipper.hpp"
22#include "Shader/PixelShader.hpp"
23#include "Shader/VertexShader.hpp"
24#include "Main/Config.hpp"
25#include "Main/FrameBuffer.hpp"
26#include "Common/Math.hpp"
27#include "Common/Configurator.hpp"
Alexis Hetu81519cf2016-09-08 13:59:50 -040028#include "Common/Memory.hpp"
Nicolas Capens0bac2852016-05-07 06:09:58 -040029#include "Common/Timer.hpp"
30#include "../common/debug.h"
31
32namespace es1
33{
34 using namespace sw;
35
36 Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
37 {
38 renderTarget = nullptr;
39 depthBuffer = nullptr;
40 stencilBuffer = nullptr;
41
42 setDepthBufferEnable(true);
43 setFillMode(FILL_SOLID);
44 setShadingMode(SHADING_GOURAUD);
45 setDepthWriteEnable(true);
46 setAlphaTestEnable(false);
47 setSourceBlendFactor(BLEND_ONE);
48 setDestBlendFactor(BLEND_ZERO);
Nicolas Capensdd4c8632018-07-31 15:33:28 -040049 setCullMode(CULL_COUNTERCLOCKWISE, true);
Nicolas Capens0bac2852016-05-07 06:09:58 -040050 setDepthCompare(DEPTH_LESSEQUAL);
51 setAlphaReference(0.0f);
52 setAlphaCompare(ALPHA_ALWAYS);
53 setAlphaBlendEnable(false);
54 setFogEnable(false);
55 setSpecularEnable(true);
56 setLocalViewer(false);
57 setFogColor(0);
58 setPixelFogMode(FOG_NONE);
59 setFogStart(0.0f);
60 setFogEnd(1.0f);
61 setFogDensity(1.0f);
62 setRangeFogEnable(false);
63 setStencilEnable(false);
64 setStencilFailOperation(OPERATION_KEEP);
65 setStencilZFailOperation(OPERATION_KEEP);
66 setStencilPassOperation(OPERATION_KEEP);
67 setStencilCompare(STENCIL_ALWAYS);
68 setStencilReference(0);
69 setStencilMask(0xFFFFFFFF);
70 setStencilWriteMask(0xFFFFFFFF);
71 setVertexFogMode(FOG_NONE);
72 setClipFlags(0);
73 setPointSize(1.0f);
74 setPointSizeMin(0.125f);
75 setPointSizeMax(8192.0f);
76 setColorWriteMask(0, 0x0000000F);
77 setBlendOperation(BLENDOP_ADD);
78 scissorEnable = false;
79 setSlopeDepthBias(0.0f);
80 setTwoSidedStencil(false);
81 setStencilFailOperationCCW(OPERATION_KEEP);
82 setStencilZFailOperationCCW(OPERATION_KEEP);
83 setStencilPassOperationCCW(OPERATION_KEEP);
84 setStencilCompareCCW(STENCIL_ALWAYS);
85 setColorWriteMask(1, 0x0000000F);
86 setColorWriteMask(2, 0x0000000F);
87 setColorWriteMask(3, 0x0000000F);
88 setBlendConstant(0xFFFFFFFF);
89 setWriteSRGB(false);
90 setDepthBias(0.0f);
91 setSeparateAlphaBlendEnable(false);
92 setSourceBlendFactorAlpha(BLEND_ONE);
93 setDestBlendFactorAlpha(BLEND_ZERO);
94 setBlendOperationAlpha(BLENDOP_ADD);
95 setPointSpriteEnable(true);
96
97 for(int i = 0; i < 16; i++)
98 {
99 setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
100 setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
101 setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
102 setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
103 setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
104 setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
105 setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
106 }
107
108 for(int i = 0; i < 4; i++)
109 {
110 setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
111 setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
112 setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
113 setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
114 setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
115 setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
116 setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
117 }
118
119 for(int i = 0; i < 6; i++)
120 {
121 float plane[4] = {0, 0, 0, 0};
122
123 setClipPlane(i, plane);
124 }
125 }
126
127 Device::~Device()
128 {
129 if(renderTarget)
130 {
131 renderTarget->release();
132 renderTarget = nullptr;
133 }
134
135 if(depthBuffer)
136 {
137 depthBuffer->release();
138 depthBuffer = nullptr;
139 }
140
141 if(stencilBuffer)
142 {
143 stencilBuffer->release();
144 stencilBuffer = nullptr;
145 }
146
147 delete context;
148 }
149
Alexis Hetu81519cf2016-09-08 13:59:50 -0400150 // This object has to be mem aligned
Nicolas Capensb7d59242017-01-03 14:02:05 -0500151 void* Device::operator new(size_t size)
152 {
153 ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class
154 return sw::allocate(sizeof(Device), 16);
155 }
156
157 void Device::operator delete(void * mem)
158 {
159 sw::deallocate(mem);
Alexis Hetu81519cf2016-09-08 13:59:50 -0400160 }
161
Nicolas Capens0bac2852016-05-07 06:09:58 -0400162 void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
163 {
164 if(!renderTarget || !rgbaMask)
165 {
166 return;
167 }
168
169 float rgba[4];
170 rgba[0] = red;
171 rgba[1] = green;
172 rgba[2] = blue;
173 rgba[3] = alpha;
174
Nicolas Capens426cb5e2017-07-20 14:14:09 -0400175 sw::Rect clearRect = renderTarget->getRect();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400176
177 if(scissorEnable)
178 {
179 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
180 }
181
182 clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask);
183 }
184
185 void Device::clearDepth(float z)
186 {
187 if(!depthBuffer)
188 {
189 return;
190 }
191
192 z = clamp01(z);
Nicolas Capens426cb5e2017-07-20 14:14:09 -0400193 sw::Rect clearRect = depthBuffer->getRect();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400194
195 if(scissorEnable)
196 {
197 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
198 }
199
200 depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
201 }
202
203 void Device::clearStencil(unsigned int stencil, unsigned int mask)
204 {
205 if(!stencilBuffer)
206 {
207 return;
208 }
209
Nicolas Capens426cb5e2017-07-20 14:14:09 -0400210 sw::Rect clearRect = stencilBuffer->getRect();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400211
212 if(scissorEnable)
213 {
214 clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
215 }
216
217 stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
218 }
219
Nicolas Capens0bac2852016-05-07 06:09:58 -0400220 void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount)
221 {
222 if(!bindResources() || !primitiveCount)
223 {
224 return;
225 }
226
227 draw(type, indexOffset, primitiveCount);
228 }
229
230 void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount)
231 {
232 if(!bindResources() || !primitiveCount)
233 {
234 return;
235 }
236
237 setIndexBuffer(nullptr);
238
239 draw(type, 0, primitiveCount);
240 }
241
242 void Device::setScissorEnable(bool enable)
243 {
244 scissorEnable = enable;
245 }
246
247 void Device::setRenderTarget(int index, egl::Image *renderTarget)
248 {
249 if(renderTarget)
250 {
251 renderTarget->addRef();
252 }
253
254 if(this->renderTarget)
255 {
256 this->renderTarget->release();
257 }
258
259 this->renderTarget = renderTarget;
260
261 Renderer::setRenderTarget(index, renderTarget);
262 }
263
264 void Device::setDepthBuffer(egl::Image *depthBuffer)
265 {
266 if(this->depthBuffer == depthBuffer)
267 {
268 return;
269 }
270
271 if(depthBuffer)
272 {
273 depthBuffer->addRef();
274 }
275
276 if(this->depthBuffer)
277 {
278 this->depthBuffer->release();
279 }
280
281 this->depthBuffer = depthBuffer;
282
283 Renderer::setDepthBuffer(depthBuffer);
284 }
285
286 void Device::setStencilBuffer(egl::Image *stencilBuffer)
287 {
288 if(this->stencilBuffer == stencilBuffer)
289 {
290 return;
291 }
292
293 if(stencilBuffer)
294 {
295 stencilBuffer->addRef();
296 }
297
298 if(this->stencilBuffer)
299 {
300 this->stencilBuffer->release();
301 }
302
303 this->stencilBuffer = stencilBuffer;
304
305 Renderer::setStencilBuffer(stencilBuffer);
306 }
307
308 void Device::setScissorRect(const sw::Rect &rect)
309 {
310 scissorRect = rect;
311 }
312
313 void Device::setViewport(const Viewport &viewport)
314 {
315 this->viewport = viewport;
316 }
317
318 bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter)
319 {
320 if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
321 {
322 ERR("Invalid parameters");
323 return false;
324 }
325
326 int sWidth = source->getWidth();
327 int sHeight = source->getHeight();
328 int dWidth = dest->getWidth();
329 int dHeight = dest->getHeight();
330
331 SliceRect sRect;
332 SliceRect dRect;
333
334 if(sourceRect)
335 {
336 sRect = *sourceRect;
337 }
338 else
339 {
340 sRect.y0 = 0;
341 sRect.x0 = 0;
342 sRect.y1 = sHeight;
343 sRect.x1 = sWidth;
344 }
345
346 if(destRect)
347 {
348 dRect = *destRect;
349 }
350 else
351 {
352 dRect.y0 = 0;
353 dRect.x0 = 0;
354 dRect.y1 = dHeight;
355 dRect.x1 = dWidth;
356 }
357
358 bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
359 bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
360 bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat());
361 bool alpha0xFF = false;
362
363 if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
364 (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
365 {
366 equalFormats = true;
367 alpha0xFF = true;
368 }
369
370 if(depthStencil) // Copy entirely, internally // FIXME: Check
371 {
372 if(source->hasDepth())
373 {
374 sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC);
375 sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC);
376
Nicolas Capens0bac2852016-05-07 06:09:58 -0400377 unsigned int height = source->getHeight();
378 unsigned int pitch = source->getInternalPitchB();
379
380 for(unsigned int y = 0; y < height; y++)
381 {
382 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes
383
384 sourceBuffer += pitch;
385 destBuffer += pitch;
386 }
387
388 source->unlockInternal();
389 dest->unlockInternal();
390 }
391
392 if(source->hasStencil())
393 {
Alexis Hetua52dfbd2016-10-05 17:03:30 -0400394 sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, 0, 0, PUBLIC);
395 sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, 0, 0, PUBLIC);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400396
Nicolas Capens0bac2852016-05-07 06:09:58 -0400397 unsigned int height = source->getHeight();
398 unsigned int pitch = source->getStencilPitchB();
399
400 for(unsigned int y = 0; y < height; y++)
401 {
402 memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes
403
404 sourceBuffer += pitch;
405 destBuffer += pitch;
406 }
407
408 source->unlockStencil();
409 dest->unlockStencil();
410 }
411 }
412 else if(!scaling && equalFormats)
413 {
414 unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC);
415 unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC);
416 unsigned int sourcePitch = source->getInternalPitchB();
417 unsigned int destPitch = dest->getInternalPitchB();
418
419 unsigned int width = dRect.x1 - dRect.x0;
420 unsigned int height = dRect.y1 - dRect.y0;
421 unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat());
422
423 for(unsigned int y = 0; y < height; y++)
424 {
425 memcpy(destBytes, sourceBytes, bytes);
426
427 if(alpha0xFF)
428 {
429 for(unsigned int x = 0; x < width; x++)
430 {
431 destBytes[4 * x + 3] = 0xFF;
432 }
433 }
434
435 sourceBytes += sourcePitch;
436 destBytes += destPitch;
437 }
438
439 source->unlockInternal();
440 dest->unlockInternal();
441 }
442 else
443 {
Alexis Hetu10c74a62017-11-29 14:00:32 -0500444 sw::SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, sRect.slice);
445 blit(source, sRectF, dest, dRect, scaling && filter);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400446 }
447
448 return true;
449 }
450
451 bool Device::bindResources()
452 {
453 if(!bindViewport())
454 {
455 return false; // Zero-area target region
456 }
457
458 return true;
459 }
460
461 bool Device::bindViewport()
462 {
463 if(viewport.width <= 0 || viewport.height <= 0)
464 {
465 return false;
466 }
467
468 if(scissorEnable)
469 {
470 if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
471 {
472 return false;
473 }
474
475 sw::Rect scissor;
476 scissor.x0 = scissorRect.x0;
477 scissor.x1 = scissorRect.x1;
478 scissor.y0 = scissorRect.y0;
479 scissor.y1 = scissorRect.y1;
480
481 setScissor(scissor);
482 }
483 else
484 {
485 sw::Rect scissor;
486 scissor.x0 = viewport.x0;
487 scissor.x1 = viewport.x0 + viewport.width;
488 scissor.y0 = viewport.y0;
489 scissor.y1 = viewport.y0 + viewport.height;
490
491 if(renderTarget)
492 {
493 scissor.x0 = max(scissor.x0, 0);
494 scissor.x1 = min(scissor.x1, renderTarget->getWidth());
495 scissor.y0 = max(scissor.y0, 0);
496 scissor.y1 = min(scissor.y1, renderTarget->getHeight());
497 }
498
499 if(depthBuffer)
500 {
501 scissor.x0 = max(scissor.x0, 0);
502 scissor.x1 = min(scissor.x1, depthBuffer->getWidth());
503 scissor.y0 = max(scissor.y0, 0);
504 scissor.y1 = min(scissor.y1, depthBuffer->getHeight());
505 }
506
507 if(stencilBuffer)
508 {
509 scissor.x0 = max(scissor.x0, 0);
510 scissor.x1 = min(scissor.x1, stencilBuffer->getWidth());
511 scissor.y0 = max(scissor.y0, 0);
512 scissor.y1 = min(scissor.y1, stencilBuffer->getHeight());
513 }
514
515 setScissor(scissor);
516 }
517
518 sw::Viewport view;
519 view.x0 = (float)viewport.x0;
520 view.y0 = (float)viewport.y0;
521 view.width = (float)viewport.width;
522 view.height = (float)viewport.height;
523 view.minZ = viewport.minZ;
524 view.maxZ = viewport.maxZ;
525
526 Renderer::setViewport(view);
527
528 return true;
529 }
530
531 bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
532 {
533 if(!rect)
534 {
535 return true;
536 }
537
538 if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
539 {
540 return false;
541 }
542
543 if(rect->x0 < 0 || rect->y0 < 0)
544 {
545 return false;
546 }
547
548 if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
549 {
550 return false;
551 }
552
553 return true;
554 }
555
556 void Device::finish()
557 {
558 synchronize();
559 }
560}