blob: ec657b52d74e9eb00e10c98b43f46d68eb93c856 [file] [log] [blame]
// SwiftShader Software Renderer
//
// Copyright(c) 2014 Google Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of Google Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//
// libRAD.cpp: Implements the exported Radiance functions.
#include "main.h"
#include "Context.h"
#include "Program.h"
#include "Shader.h"
#include "Texture.h"
#include "common/debug.h"
#include "Common/Version.h"
#include "Main/Register.hpp"
#include "Surface.h"
#define GL_APICALL
#include <RAD/rad.h>
#include <limits>
#include <deque>
#include <set>
namespace rad
{
class Object;
typedef std::set<const Object*> ObjectPool;
class Device
{
public:
Device()
{
referenceCount = 1;
}
void reference()
{
sw::atomicIncrement(&referenceCount);
}
void release()
{
ASSERT(referenceCount > 0);
if(referenceCount > 0)
{
sw::atomicDecrement(&referenceCount);
}
if(referenceCount == 0)
{
delete this;
}
}
void addObject(const Object *object)
{
pool.insert(object);
}
void removeObject(const Object *object)
{
pool.erase(object);
}
private:
virtual ~Device()
{
ASSERT(referenceCount == 0);
size_t leakedObjectCount = pool.size();
if(leakedObjectCount != 0)
{
const Object *leakedObject = *pool.begin();
ASSERT(!leakedObject);
}
}
volatile int referenceCount;
ObjectPool pool;
};
class Object
{
public:
Object(Device *device) : device(device)
{
referenceCount = 1;
device->addObject(this);
}
void reference()
{
sw::atomicIncrement(&referenceCount);
}
void release()
{
ASSERT(referenceCount > 0);
if(referenceCount > 0)
{
sw::atomicDecrement(&referenceCount);
}
if(referenceCount == 0)
{
device->removeObject(this);
delete this;
}
}
protected:
virtual ~Object()
{
ASSERT(referenceCount == 0);
}
Device *const device;
private:
volatile int referenceCount;
};
static void Release(Object *object)
{
if(object)
{
object->release();
}
}
class Buffer : public Object
{
public:
Buffer(Device *device) : Object(device)
{
buffer = nullptr;
access = 0; // FIXME: default?
mapAccess = 0; // FIXME: default?
}
virtual ~Buffer()
{
if(buffer)
{
buffer->destruct();
}
}
void storage(RADsizei size)
{
ASSERT(!buffer);
const int padding = 1024; // For SIMD processing of vertices
buffer = new sw::Resource(size + padding);
}
void *map()
{
ASSERT(buffer);
return const_cast<void*>(buffer->data());
}
sw::Resource *buffer;
RADbitfield access;
RADbitfield mapAccess;
};
class Sampler : public Object
{
public:
Sampler(Device *device) : Object(device)
{
defaults();
}
virtual ~Sampler()
{
}
void defaults()
{
minFilter = RAD_MIN_FILTER_NEAREST_MIPMAP_LINEAR; // FIXME: default?
magFilter = RAD_MAG_FILTER_LINEAR; // FIXME: default?
wrapModeS = RAD_WRAP_MODE_REPEAT; // FIXME: default?
wrapModeT = RAD_WRAP_MODE_REPEAT; // FIXME: default?
wrapModeR = RAD_WRAP_MODE_REPEAT; // FIXME: default?
minLod = -1000.0f; // FIXME: default?
maxLod = 1000.0f; // FIXME: default?
lodBias = 0.0f;
compareMode = RAD_COMPARE_MODE_NONE;
compareFunc = RAD_COMPARE_FUNC_LEQUAL; // FIXME: default?
borderColor[0] = 0.0f; // FIXME: default?
borderColor[1] = 0.0f; // FIXME: default?
borderColor[2] = 0.0f; // FIXME: default?
borderColor[3] = 0.0f; // FIXME: default?
borderColorInt[0] = 0; // FIXME: default?
borderColorInt[1] = 0; // FIXME: default?
borderColorInt[2] = 0; // FIXME: default?
borderColorInt[3] = 0; // FIXME: default?
}
RADminFilter minFilter;
RADmagFilter magFilter;
RADwrapMode wrapModeS;
RADwrapMode wrapModeT;
RADwrapMode wrapModeR;
RADfloat minLod;
RADfloat maxLod;
RADfloat lodBias;
RADcompareMode compareMode;
RADcompareFunc compareFunc;
RADfloat borderColor[4];
RADuint borderColorInt[4];
};
class Texture;
struct TextureSampler
{
TextureSampler(Texture *texture, Sampler *sampler, RADtextureTarget target, RADinternalFormat internalFormat, RADuint minLevel, RADuint numLevels, RADuint minLayer, RADuint numLayers);
virtual ~TextureSampler();
Texture *texture;
Sampler *sampler;
RADtextureTarget target;
RADinternalFormat internalFormat;
RADuint minLevel;
RADuint numLevels;
RADuint minLayer;
RADuint numLayers;
};
class Texture : public Object
{
public:
Texture(Device *device) : Object(device)
{
texture = nullptr;
access = 0; // FIXME: default?
//target = 0;
//levels = 0;
//internalFormat = 0;
//width = 0;
//height = 0;
//depth = 0;
//samples = 0;
}
virtual ~Texture()
{
if(texture)
{
texture->release();
}
for(size_t i = 0; i < textureSamplers.size(); i++)
{
delete textureSamplers[i];
}
}
es2::Texture *texture;
RADbitfield access;
RADtextureTarget target;
RADsizei levels;
RADinternalFormat internalFormat;
RADsizei width;
RADsizei height;
RADsizei depth;
RADsizei samples;
std::vector<TextureSampler*> textureSamplers;
};
TextureSampler::TextureSampler(Texture *texture, Sampler *sampler, RADtextureTarget target, RADinternalFormat internalFormat, RADuint minLevel, RADuint numLevels, RADuint minLayer, RADuint numLayers)
{
ASSERT(texture);
ASSERT(sampler);
//texture->reference();
this->texture = texture;
//sampler->reference();
this->sampler = sampler;
this->target = target;
this->internalFormat = internalFormat;
this->minLevel = minLevel;
this->numLevels = numLevels;
this->minLayer = minLayer;
this->numLayers = numLayers;
}
TextureSampler::~TextureSampler()
{
//texture->release();
//sampler->release();
}
class Pass;
class Program : public Object
{
public:
Program(Device *device) : Object(device)
{
program = new es2::Program(0);
program->addRef();
}
virtual ~Program()
{
program->release();
}
es2::Program *program;
};
template<typename T, size_t n>
inline size_t arraySize(T(&)[n])
{
return n;
}
const int RAD_MAX_COLOR_TARGETS = 1;
struct ColorState : public Object
{
ColorState(Device *device) : Object(device)
{
defaults();
}
void defaults()
{
enable = RAD_FALSE;
for(size_t i = 0; i < arraySize(blend); i++)
{
blend[i].defaults();
}
numTargets = 1;
logicOpEnable = RAD_FALSE;
logicOp = RAD_LOGIC_OP_COPY;
alphaToCoverageEnable = RAD_FALSE;
blendColor[0] = 0.0f;
blendColor[1] = 0.0f;
blendColor[2] = 0.0f;
blendColor[3] = 0.0f;
}
RADboolean enable;
struct Blend
{
Blend()
{
defaults();
}
void defaults()
{
enable = RAD_FALSE;
srcFunc = RAD_BLEND_FUNC_ONE;
dstFunc = RAD_BLEND_FUNC_ZERO;
srcFuncAlpha = RAD_BLEND_FUNC_ONE;
dstFuncAlpha = RAD_BLEND_FUNC_ZERO;
modeRGB = RAD_BLEND_EQUATION_ADD;
modeAlpha = RAD_BLEND_EQUATION_ADD;
maskRGBA[0] = RAD_TRUE;
maskRGBA[1] = RAD_TRUE;
maskRGBA[2] = RAD_TRUE;
maskRGBA[3] = RAD_TRUE;
}
RADboolean enable;
RADblendFunc srcFunc;
RADblendFunc dstFunc;
RADblendFunc srcFuncAlpha;
RADblendFunc dstFuncAlpha;
RADblendEquation modeRGB;
RADblendEquation modeAlpha;
RADboolean maskRGBA[4];
};
Blend blend[RAD_MAX_COLOR_TARGETS];
RADuint numTargets;
RADboolean logicOpEnable;
RADlogicOp logicOp;
RADboolean alphaToCoverageEnable;
RADfloat blendColor[4];
};
struct RasterState : public Object
{
RasterState(Device *device) : Object(device)
{
defaults();
}
void defaults()
{
pointSize = 1.0f;
lineWidth = 1.0f;
cullFace = RAD_FACE_NONE;
frontFace = RAD_FRONT_FACE_CW;
polygonMode = RAD_POLYGON_MODE_FILL;
offsetFactor = 0.0f;
offsetUnits = 0.0f;
offsetClamp = 0.0f;
polygonOffsetEnables = RAD_POLYGON_OFFSET_NONE;
discardEnable = RAD_FALSE;
multisampleEnable = RAD_TRUE;
samples = 0;
sampleMask = ~0;
}
RADfloat pointSize;
RADfloat lineWidth;
RADfaceBitfield cullFace;
RADfrontFace frontFace;
RADpolygonMode polygonMode;
RADfloat offsetFactor;
RADfloat offsetUnits;
RADfloat offsetClamp;
RADpolygonOffsetEnables polygonOffsetEnables;
RADboolean discardEnable;
RADboolean multisampleEnable;
RADuint samples;
RADuint sampleMask;
};
struct DepthStencilState : public Object
{
DepthStencilState(Device *device) : Object(device)
{
defaults();
}
void defaults()
{
depthTestEnable = RAD_FALSE;
depthWriteEnable = RAD_FALSE;
depthFunc = RAD_DEPTH_FUNC_LESS;
stencilTestEnable = RAD_FALSE;
stencilFuncFront = RAD_STENCIL_FUNC_ALWAYS;
stencilRefFront = 0;
stencilMaskFront = ~0;
stencilFuncBack = RAD_STENCIL_FUNC_ALWAYS;
stencilRefBack = 0;
stencilMaskBack = ~0;
stencilFailOpFront = RAD_STENCIL_OP_KEEP;
depthFailOpFront = RAD_STENCIL_OP_KEEP;
depthPassOpFront = RAD_STENCIL_OP_KEEP;
stencilFailOpBack = RAD_STENCIL_OP_KEEP;
depthFailOpBack = RAD_STENCIL_OP_KEEP;
depthPassOpBack = RAD_STENCIL_OP_KEEP;
stencilWriteMaskFront = ~0;
stencilWriteMaskBack = ~0;
}
RADboolean depthTestEnable;
RADboolean depthWriteEnable;
RADdepthFunc depthFunc;
RADboolean stencilTestEnable;
RADstencilFunc stencilFuncFront;
RADint stencilRefFront;
RADuint stencilMaskFront;
RADstencilFunc stencilFuncBack;
RADint stencilRefBack;
RADuint stencilMaskBack;
RADstencilOp stencilFailOpFront;
RADstencilOp depthFailOpFront;
RADstencilOp depthPassOpFront;
RADstencilOp stencilFailOpBack;
RADstencilOp depthFailOpBack;
RADstencilOp depthPassOpBack;
RADuint stencilWriteMaskFront;
RADuint stencilWriteMaskBack;
};
const int RAD_MAX_VERTEX_ATTRIB = 16;
const int RAD_MAX_VERTEX_BINDING = 16;
struct VertexState : public Object
{
VertexState(Device *device) : Object(device)
{
defaults();
}
void defaults()
{
for(size_t i = 0; i < arraySize(attrib); i++)
{
attrib[i].defaults();
}
for(size_t i = 0; i < arraySize(binding); i++)
{
binding[i].defaults();
}
}
struct Attribute
{
Attribute()
{
defaults();
}
void defaults()
{
enable = RAD_FALSE;
bindingIndex = 0;
numComponents = 0;
bytesPerComponent = 0;
type = RAD_ATTRIB_TYPE_SNORM;
relativeOffset = 0;
}
RADboolean enable;
RADint bindingIndex;
RADint numComponents;
RADint bytesPerComponent;
RADattribType type;
RADuint relativeOffset;
};
Attribute attrib[RAD_MAX_VERTEX_ATTRIB];
struct Binding
{
Binding()
{
defaults();
}
void defaults()
{
group = 0;
index = 0;
stride = 0;
}
RADint group;
RADint index;
RADuint stride;
};
Binding binding[RAD_MAX_VERTEX_BINDING];
};
struct FormatState : public Object
{
FormatState(Device *device) : Object(device)
{
defaults();
}
void defaults()
{
for(size_t i = 0; i < arraySize(colorFormat); i++)
{
colorFormat[i] = RAD_FORMAT_NONE;
}
depthFormat = RAD_FORMAT_NONE;
stencilFormat = RAD_FORMAT_NONE;
colorSamples = 0;
depthStencilSamples = 0;
}
RADinternalFormat colorFormat[RAD_MAX_COLOR_TARGETS];
RADinternalFormat depthFormat;
RADinternalFormat stencilFormat;
RADuint colorSamples;
RADuint depthStencilSamples;
};
class Pipeline : public Object
{
public:
Pipeline(Device *device) : Object(device)
{
vertexProgram = nullptr;
fragmentProgram = nullptr;
vertexState = nullptr;
colorState = nullptr;
rasterState = nullptr;
depthStencilState = nullptr;
formatState = nullptr;
primitiveType = RAD_TRIANGLES;
}
virtual ~Pipeline()
{
Release(vertexProgram);
Release(fragmentProgram);
Release(vertexState);
Release(colorState);
Release(rasterState);
Release(depthStencilState);
Release(formatState);
}
Program *vertexProgram;
Program *fragmentProgram;
VertexState *vertexState;
ColorState *colorState;
RasterState *rasterState;
DepthStencilState *depthStencilState;
FormatState *formatState;
RADprimitiveType primitiveType;
};
const int RAD_MAX_ATTACHMENTS = 1 /*depth*/ + 1 /*stencil*/ + RAD_MAX_COLOR_TARGETS;
class Pass : public Object
{
public:
Pass(Device *device) : Object(device)
{
defaults();
}
virtual ~Pass()
{
for(size_t i = 0; i < arraySize(colorTarget); i++)
{
if(colorTarget[i])
{
colorTarget[i]->release();
}
}
if(depthTarget)
{
depthTarget->release();
}
if(stencilTarget)
{
stencilTarget->release();
}
}
void defaults()
{
numColors = 0;
for(size_t i = 0; i < arraySize(colorTarget); i++)
{
colorTarget[i] = nullptr;
}
depthTarget = nullptr;
stencilTarget = nullptr;
for(size_t i = 0; i < arraySize(preserveEnable); i++)
{
preserveEnable[i] = RAD_TRUE;
}
}
RADuint numColors;
es2::Image *colorTarget[RAD_MAX_COLOR_TARGETS];
es2::Image *depthTarget;
es2::Image *stencilTarget;
RADboolean preserveEnable[RAD_MAX_ATTACHMENTS];
//RADuint numDiscardTextures;
//const RADtexture *discardTextures;
//const RADoffset2D *discardOffsets;
//
//RADtexture resolveTexture[RAD_MAX_ATTACHMENTS];
//RADuint numStoreTextures;
//const RADtexture *storeTextures;
//const RADoffset2D *storeOffsets;
//
//const RADrect2D *clipRect;
//RADuint numDependencies;
//const RADpass *dependentPasses;
//const RADbitfield *srcMask;
//const RADbitfield *dstMask;
//const RADbitfield *flushMask;
//const RADbitfield *invalidateMask;
//RADboolean tilingBoundary;
//RADuint tileFilterWidth;
//RADuint tileTilterHeight;
//RADuint bytesPerPixel;
//RADuint footprintFilterWidth;
//RADuint footprintFilterHeight;
};
class Command
{
public:
Command()
{
//pipeline = nullptr;
//pass = nullptr;
}
virtual ~Command()
{
//Release(pipeline);
//Release(pass);
}
virtual void execute(Pipeline *pipeline, Pass *pass) = 0; // FIXME: Just queue as parameter?
virtual bool isPresent() const
{
return false;
}
//void setPipeline(Pipeline *pipeline)
//{
// if(pipeline)
// {
// pipeline->reference();
// this->pipeline = pipeline;
// }
//}
//void setPass(Pass *pass)
//{
// if(pass)
// {
// pass->reference();
// this->pass = pass;
// }
//}
protected:
//Pipeline *pipeline; // FIXME: Command-specific state captured in their constructor?
//Pass *pass;
};
class CopyBufferToImage : public Command
{
public:
CopyBufferToImage(Buffer *buffer, RADintptr bufferOffset, Texture *texture, RADint level, RADuint xoffset, RADuint yoffset, RADuint zoffset, RADsizei width, RADsizei height, RADsizei depth)
{
ASSERT(buffer);
ASSERT(texture);
buffer->reference();
this->buffer = buffer;
this->bufferOffset = bufferOffset;
texture->reference();
this->texture = texture;
this->level = level;
this->xoffset = xoffset;
this->yoffset = yoffset;
this->zoffset = zoffset;
this->width = width;
this->height = height;
this->depth = depth;
}
virtual ~CopyBufferToImage()
{
buffer->release();
texture->release();
}
virtual void execute(Pipeline *pipeline, Pass *pass)
{
ASSERT(depth == 1); // FIXME: Unimplemented
egl::Image *image = texture->texture->getRenderTarget(GL_TEXTURE_2D, level);
uint8_t *output = static_cast<uint8_t*>(image->lock(xoffset, yoffset, sw::LOCK_WRITEONLY)); // FIXME: Discard if whole image
unsigned int pitch = image->getPitch();
const uint8_t *input = static_cast<const uint8_t*>(buffer->map()) + bufferOffset; // FIXME: Necessary to lock?
ASSERT(texture->internalFormat == RAD_RGBA8); // FIXME: Unimplemented
int bytesPerTexel = 4;
for(int y = 0; y < height; y++)
{
const uint8_t *source = input + y * (width * bytesPerTexel);
uint8_t *dest = output + y * pitch;
memcpy(dest, source, width * bytesPerTexel);
}
image->unlock();
image->release();
}
Buffer *buffer;
RADintptr bufferOffset;
Texture *texture;
RADint level;
RADuint xoffset;
RADuint yoffset;
RADuint zoffset;
RADsizei width;
RADsizei height;
RADsizei depth;
};
class Scissor : public Command
{
public:
Scissor(RADint x, RADint y, RADint w, RADint h)
{
this->x = x;
this->y = y;
this->w = w;
this->h = h;
}
virtual ~Scissor()
{
}
virtual void execute(Pipeline *pipeline, Pass *pass)
{
es2::Context *context = es2::getContext();
context->setScissorParams(x, y, w, h);
}
RADint x;
RADint y;
RADint w;
RADint h;
};
class Viewport : public Command
{
public:
Viewport(RADint x, RADint y, RADint w, RADint h)
{
this->x = x;
this->y = y;
this->w = w;
this->h = h;
}
virtual ~Viewport()
{
}
virtual void execute(Pipeline *pipeline, Pass *pass)
{
es2::Context *context = es2::getContext();
context->setViewportParams(x, y, w, h);
}
RADint x;
RADint y;
RADint w;
RADint h;
};
class ClearColor : public Command
{
public:
ClearColor(RADuint index, const RADfloat *color)
{
this->index = index;
this->color[0] = color[0];
this->color[1] = color[1];
this->color[2] = color[2];
this->color[3] = color[3];
}
virtual ~ClearColor()
{
}
virtual void execute(Pipeline *pipeline, Pass *pass)
{
ASSERT(pass); // FIXME: Error if no beginPass
ASSERT(index < pass->numColors);
es2::Image *image = pass->colorTarget[index];
GLenum format = image->getFormat();
GLenum type = image->getType();
ASSERT(format == GL_RGBA); // FIXME
ASSERT(type == GL_UNSIGNED_BYTE); // FIXME
es2::Context *context = es2::getContext();
int x0 = context->mState.scissorX;
int y0 = context->mState.scissorY;
int width = context->mState.scissorWidth;
int height = context->mState.scissorHeight;
image->clearColorBuffer(sw::Color<float>(color[0], color[1], color[2], color[3]), 0xF, x0, y0, width, height);
}
RADuint index;
RADfloat color[4];
};
class ClearDepth : public Command
{
public:
ClearDepth(RADfloat depth)
{
this->depth = depth;
}
virtual ~ClearDepth()
{
}
virtual void execute(Pipeline *pipeline, Pass *pass)
{
ASSERT(pass); // FIXME: Error if no beginPass
es2::Image *image = pass->depthTarget;
es2::Context *context = es2::getContext();
int x0 = context->mState.scissorX;
int y0 = context->mState.scissorY;
int width = context->mState.scissorWidth;
int height = context->mState.scissorHeight;
image->clearDepthBuffer(depth, x0, y0, width, height);
}
RADfloat depth;
};
class Present : public Command
{
public:
Present(Texture *texture)
{
texture->reference();
this->texture = texture;
}
virtual ~Present()
{
Release(texture);
}
virtual void execute(Pipeline *pipeline, Pass *pass)
{
es2::Context *context = es2::getContext();
sw::FrameBuffer *frameBuffer = (*es2::getDisplay()->mSurfaceSet.begin())->frameBuffer;
egl::Image *image = texture->texture->getRenderTarget(GL_TEXTURE_2D, 0);
void *source = image->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
frameBuffer->flip(source, image->getInternalFormat());
image->unlockInternal();
image->release();
}
virtual bool isPresent() const
{
return true;
}
Texture *texture;
};
class DrawElements : public Command
{
public:
DrawElements(RADprimitiveType mode, RADindexType type, RADsizei count, sw::Resource *indexBuffer, RADuint offset)
{
this->mode = mode;
this->type = type;
this->count = count;
this->indexBuffer = indexBuffer;
this->offset = offset;
}
~DrawElements()
{
}
virtual void execute(Pipeline *pipeline, Pass *pass)
{
es2::Context *context = es2::getContext();
ASSERT(pipeline->vertexProgram == pipeline->fragmentProgram); // FIXME
context->mState.program = pipeline->vertexProgram->program;
GLenum glType = GL_UNSIGNED_SHORT;
switch(type)
{
case RAD_INDEX_UNSIGNED_BYTE: glType = GL_UNSIGNED_BYTE; break;
case RAD_INDEX_UNSIGNED_SHORT: glType = GL_UNSIGNED_SHORT; break;
case RAD_INDEX_UNSIGNED_INT: glType = GL_UNSIGNED_INT; break;
default: UNREACHABLE();
}
GLenum glMode = GL_TRIANGLES;
switch(mode)
{
case RAD_TRIANGLES: glMode = GL_TRIANGLES; break;
default: UNREACHABLE();
}
context->mState.colorBuffer = pass->colorTarget[0];
context->mState.depthBuffer = pass->depthTarget;
context->mState.depthTest = pipeline->depthStencilState->depthTestEnable;
GLenum glDepth = GL_LESS;
switch(pipeline->depthStencilState->depthFunc)
{
case RAD_DEPTH_FUNC_NEVER: glDepth = GL_NEVER; break;
case RAD_DEPTH_FUNC_LESS: glDepth = GL_LESS; break;
case RAD_DEPTH_FUNC_EQUAL: glDepth = GL_EQUAL; break;
case RAD_DEPTH_FUNC_LEQUAL: glDepth = GL_LEQUAL; break;
case RAD_DEPTH_FUNC_GREATER: glDepth = GL_GREATER; break;
case RAD_DEPTH_FUNC_NOTEQUAL: glDepth = GL_NOTEQUAL; break;
case RAD_DEPTH_FUNC_GEQUAL: glDepth = GL_GEQUAL; break;
case RAD_DEPTH_FUNC_ALWAYS: glDepth = GL_ALWAYS; break;
default: UNREACHABLE();
}
context->mState.elementArrayBuffer = indexBuffer;
context->drawElements(glMode, count, glType, 0);
}
RADprimitiveType mode;
RADindexType type;
RADsizei count;
sw::Resource *indexBuffer;
RADuint offset;
};
class BindGroup : public Command
{
public:
BindGroup(RADbitfield stages, RADuint group, RADuint count, sw::Resource *buffer, RADuint offset)
{
this->stages = stages;
this->group = group;
this->count = count;
this->buffer = buffer;
this->offset = offset;
}
virtual ~BindGroup()
{
}
virtual void execute(Pipeline *pipeline, Pass *pass)
{
es2::Context *context = es2::getContext();
const RADbindGroupElement *groupElements = static_cast<const RADbindGroupElement*>(buffer->data());
// FIXME: Should parse the layout out of the shaders
es2::Program *program = pipeline->vertexProgram->program;
sw::Resource *element0 = reinterpret_cast<sw::Resource*>(groupElements[0].handle);
uintptr_t offset0 = static_cast<uintptr_t>(groupElements[0].offset);
int position = program->getAttributeLocation("position");
context->setVertexAttribState(position, element0, 3, GL_FLOAT, GL_TRUE, 0, offset0);
context->setEnableVertexAttribArray(position, true);
sw::Resource *element1 = reinterpret_cast<sw::Resource*>(groupElements[1].handle);
uintptr_t offset1 = static_cast<uintptr_t>(groupElements[1].offset);
int tc = program->getAttributeLocation("tc");
context->setVertexAttribState(tc, element1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, offset1);
context->setEnableVertexAttribArray(tc, true);
sw::Resource *element2 = reinterpret_cast<sw::Resource*>(groupElements[2].handle);
const void *uniform = static_cast<const uint8_t*>(element2->data()) + groupElements[2].offset;
int scale = program->getUniformLocation("scale");
program->setUniform4fv(scale, 1, (const GLfloat*)uniform);
rad::TextureSampler *element3 = reinterpret_cast<rad::TextureSampler*>(groupElements[3].handle);
int tex = program->getUniformLocation("tex");
int sampler = 0;
program->setUniform1iv(tex, 1, &sampler);
context->applyTexture(sw::SAMPLER_PIXEL, sampler, element3->texture->texture);
}
RADbitfield stages;
RADuint group;
RADuint count;
sw::Resource *buffer;
RADuint offset;
};
class Queue : public Object
{
public:
Queue(Device *device) : Object(device)
{
graphicsPipeline = nullptr;
pass = nullptr;
}
virtual ~Queue()
{
for(size_t i = 0; i < commands.size(); i++)
{
delete commands[i];
}
Release(graphicsPipeline);
ASSERT(!pass); // FIXME: No matching endPass
Release(pass);
}
void submit(Command *command)
{
// FIXME: Make BeginPass/EndPass/BindPipeline commands too?
//command->setPipeline(graphicsPipeline);
//command->setPass(pass);
if(false) // Queued execution
{
commands.push_back(command);
if(command->isPresent())
{
// FIXME: Flush
}
}
else // Immediate execution
{
command->execute(graphicsPipeline, pass);
delete command;
}
}
void bindPipeline(RADpipelineType pipelineType, Pipeline *pipeline)
{
if(pipelineType == RAD_PIPELINE_TYPE_GRAPHICS)
{
pipeline->reference();
if(graphicsPipeline)
{
graphicsPipeline->release();
}
graphicsPipeline = pipeline;
}
else UNREACHABLE();
}
void beginPass(rad::Pass *pass)
{
ASSERT(!this->pass); // FIXME: Can be nested?
pass->reference();
this->pass = pass;
}
void endPass(rad::Pass *pass)
{
ASSERT(this->pass == pass); // FIXME: Can be nested?
this->pass->release();
this->pass = nullptr;
}
private:
std::deque<Command*> commands;
Pipeline *graphicsPipeline;
Pass *pass;
};
}
extern "C"
{
RADdevice RADAPIENTRY radCreateDevice(void)
{
static rad::Device *device = new rad::Device();
return reinterpret_cast<RADdevice>(device);
}
void RADAPIENTRY radReferenceDevice(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
return radDevice->reference();
}
void RADAPIENTRY radReleaseDevice(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
return radDevice->release();
}
RADuint RADAPIENTRY radGetTokenHeader(RADdevice device, RADtokenName name) {UNIMPLEMENTED(); return 0;}
RADqueue RADAPIENTRY radCreateQueue(RADdevice device, RADqueueType queuetype)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::Queue *queue = new rad::Queue(radDevice);
return reinterpret_cast<RADqueue>(queue);
}
void RADAPIENTRY radReferenceQueue(RADqueue queue)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
return radQueue->reference();
}
void RADAPIENTRY radReleaseQueue(RADqueue queue)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
return radQueue->release();
}
void RADAPIENTRY radQueueTagBuffer(RADqueue queue, RADbuffer buffer) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueTagTexture(RADqueue queue, RADtexture texture) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueSubmitCommands(RADqueue queue, RADuint numCommands, const RADcommandHandle *handles)
{
return;
}
void RADAPIENTRY radFlushQueue(RADqueue queue) {UNIMPLEMENTED();}
void RADAPIENTRY radFinishQueue(RADqueue queue) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueViewport(RADqueue queue, RADint x, RADint y, RADint w, RADint h)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::Viewport *command = new rad::Viewport(x, y, w, h);
radQueue->submit(command);
}
void RADAPIENTRY radQueueScissor(RADqueue queue, RADint x, RADint y, RADint w, RADint h)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::Scissor *command = new rad::Scissor(x, y, w, h);
radQueue->submit(command);
}
void RADAPIENTRY radQueueCopyBufferToImage(RADqueue queue, RADbuffer buffer, RADintptr bufferOffset, RADtexture texture, RADint level, RADuint xoffset, RADuint yoffset, RADuint zoffset, RADsizei width, RADsizei height, RADsizei depth)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
rad::Texture *radTexture = reinterpret_cast<rad::Texture*>(texture);
rad::CopyBufferToImage *command = new rad::CopyBufferToImage(radBuffer, bufferOffset, radTexture, level, xoffset, yoffset, zoffset, width, height, depth);
radQueue->submit(command);
}
void RADAPIENTRY radQueueCopyImageToBuffer(RADqueue queue, RADbuffer buffer, RADintptr bufferOffset, RADtexture texture, RADint level, RADuint xoffset, RADuint yoffset, RADuint zoffset, RADsizei width, RADsizei height, RADsizei depth) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueCopyBuffer(RADqueue queue, RADbuffer srcBuffer, RADintptr srcOffset, RADbuffer dstBuffer, RADintptr dstOffset, RADsizei size)
{
return;
}
void RADAPIENTRY radQueueClearColor(RADqueue queue, RADuint index, const RADfloat *color)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::ClearColor *command = new rad::ClearColor(index, color);
radQueue->submit(command);
}
void RADAPIENTRY radQueueClearDepth(RADqueue queue, RADfloat depth)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::ClearDepth *command = new rad::ClearDepth(depth);
radQueue->submit(command);
}
void RADAPIENTRY radQueueClearStencil(RADqueue queue, RADuint stencil) {UNIMPLEMENTED();}
void RADAPIENTRY radQueuePresent(RADqueue queue, RADtexture texture)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::Texture *radTexture = reinterpret_cast<rad::Texture*>(texture);
rad::Present *command = new rad::Present(radTexture);
radQueue->submit(command);
}
void RADAPIENTRY radQueueDrawArrays(RADqueue queue, RADprimitiveType mode, RADint first, RADsizei count) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueDrawElements(RADqueue queue, RADprimitiveType mode, RADindexType type, RADsizei count, RADindexHandle indexHandle, RADuint offset)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
sw::Resource *indexBuffer = reinterpret_cast<sw::Resource*>(indexHandle);
rad::DrawElements *command = new rad::DrawElements(mode, type, count, indexBuffer, offset);
radQueue->submit(command);
}
void RADAPIENTRY radQueueBindPipeline(RADqueue queue, RADpipelineType pipelineType, RADpipelineHandle pipelineHandle)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipelineHandle);
radQueue->bindPipeline(pipelineType, radPipeline);
}
void RADAPIENTRY radQueueBindGroup(RADqueue queue, RADbitfield stages, RADuint group, RADuint count, RADbindGroupHandle groupHandle, RADuint offset)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
sw::Resource *groupBuffer = reinterpret_cast<sw::Resource*>(groupHandle);
rad::BindGroup *command = new rad::BindGroup(stages, group, count, groupBuffer, offset);
radQueue->submit(command);
}
void RADAPIENTRY radQueueBeginPass(RADqueue queue, RADpass pass)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::Pass *radPass = reinterpret_cast<rad::Pass*>(pass);
radQueue->beginPass(radPass);
}
void RADAPIENTRY radQueueEndPass(RADqueue queue, RADpass pass)
{
rad::Queue *radQueue = reinterpret_cast<rad::Queue*>(queue);
rad::Pass *radPass = reinterpret_cast<rad::Pass*>(pass);
radQueue->endPass(radPass);
}
void RADAPIENTRY radQueueSubmitDynamic(RADqueue queue, const void *dynamic, RADsizei length) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueStencilValueMask(RADqueue queue, RADfaceBitfield faces, RADuint mask) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueStencilMask(RADqueue queue, RADfaceBitfield faces, RADuint mask) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueStencilRef(RADqueue queue, RADfaceBitfield faces, RADint ref) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueBlendColor(RADqueue queue, const RADfloat *blendColor) {UNIMPLEMENTED();}
void RADAPIENTRY radQueuePointSize(RADqueue queue, RADfloat pointSize) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueLineWidth(RADqueue queue, RADfloat lineWidth) {UNIMPLEMENTED();}
void RADAPIENTRY radQueuePolygonOffsetClamp(RADqueue queue, RADfloat factor, RADfloat units, RADfloat clamp) {UNIMPLEMENTED();}
void RADAPIENTRY radQueueSampleMask(RADqueue queue, RADuint mask) {UNIMPLEMENTED();}
RADprogram RADAPIENTRY radCreateProgram(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::Program *program = new rad::Program(radDevice);
return reinterpret_cast<RADprogram>(program);
}
void RADAPIENTRY radReferenceProgram(RADprogram program)
{
rad::Program *radProgram = reinterpret_cast<rad::Program*>(program);
radProgram->reference();
}
void RADAPIENTRY radReleaseProgram(RADprogram program)
{
rad::Program *radProgram = reinterpret_cast<rad::Program*>(program);
radProgram->release();
}
void RADAPIENTRY radProgramSource(RADprogram program, RADprogramFormat format, RADsizei length, const void *source)
{
rad::Program *radProgram = reinterpret_cast<rad::Program*>(program);
// FIXME: Assumes first source is vertex shader, second is fragment shader
ASSERT(length == 2);
const char *vertexSource = static_cast<const char* const*>(source)[0];
const char *fragmentSource = static_cast<const char* const*>(source)[1];
GLint vertexLength = strlen(vertexSource);
GLint fragmentLength = strlen(fragmentSource);
es2::VertexShader *vertexShader = new es2::VertexShader(0);
vertexShader->addRef();
es2::FragmentShader *fragmentShader = new es2::FragmentShader(0);
fragmentShader->addRef();
vertexShader->setSource(1, &vertexSource, &vertexLength);
fragmentShader->setSource(1, &fragmentSource, &fragmentLength);
vertexShader->compile();
fragmentShader->compile();
radProgram->program->attachShader(vertexShader);
radProgram->program->attachShader(fragmentShader);
radProgram->program->link();
vertexShader->release(); // Still referenced by program
fragmentShader->release(); // Still referenced by program
}
RADbuffer RADAPIENTRY radCreateBuffer(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::Buffer *buffer = new rad::Buffer(radDevice);
return reinterpret_cast<RADbuffer>(buffer);
}
void RADAPIENTRY radReferenceBuffer(RADbuffer buffer)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
radBuffer->reference();
}
void RADAPIENTRY radReleaseBuffer(RADbuffer buffer, RADtagMode tagMode)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
radBuffer->release();
}
void RADAPIENTRY radBufferAccess(RADbuffer buffer, RADbitfield access)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
radBuffer->access = access;
}
void RADAPIENTRY radBufferMapAccess(RADbuffer buffer, RADbitfield mapAccess)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
radBuffer->mapAccess = mapAccess;
}
void RADAPIENTRY radBufferStorage(RADbuffer buffer, RADsizei size)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
radBuffer->storage(size);
}
void* RADAPIENTRY radMapBuffer(RADbuffer buffer)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
return radBuffer->map();
}
RADvertexHandle RADAPIENTRY radGetVertexHandle(RADbuffer buffer)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
return reinterpret_cast<RADvertexHandle>(radBuffer->buffer);
}
RADindexHandle RADAPIENTRY radGetIndexHandle(RADbuffer buffer)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
return reinterpret_cast<RADvertexHandle>(radBuffer->buffer);
}
RADuniformHandle RADAPIENTRY radGetUniformHandle(RADbuffer buffer)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
return reinterpret_cast<RADuniformHandle>(radBuffer->buffer);
}
RADbindGroupHandle RADAPIENTRY radGetBindGroupHandle(RADbuffer buffer)
{
rad::Buffer *radBuffer = reinterpret_cast<rad::Buffer*>(buffer);
return reinterpret_cast<RADbindGroupHandle>(radBuffer->buffer);
}
RADtexture RADAPIENTRY radCreateTexture(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::Texture *colorState = new rad::Texture(radDevice);
return reinterpret_cast<RADtexture>(colorState);
}
void RADAPIENTRY radReferenceTexture(RADtexture texture)
{
rad::Texture *radTexture = reinterpret_cast<rad::Texture*>(texture);
radTexture->reference();
}
void RADAPIENTRY radReleaseTexture(RADtexture texture, RADtagMode tagMode)
{
rad::Texture *radTexture = reinterpret_cast<rad::Texture*>(texture);
radTexture->release();
}
void RADAPIENTRY radTextureAccess(RADtexture texture, RADbitfield access)
{
rad::Texture *radTexture = reinterpret_cast<rad::Texture*>(texture);
radTexture->access = access;
}
void RADAPIENTRY radTextureStorage(RADtexture texture, RADtextureTarget target, RADsizei levels, RADinternalFormat internalFormat, RADsizei width, RADsizei height, RADsizei depth, RADsizei samples)
{
rad::Texture *radTexture = reinterpret_cast<rad::Texture*>(texture);
ASSERT(!radTexture->texture);
radTexture->target = target;
radTexture->levels = levels;
radTexture->internalFormat = internalFormat;
radTexture->width = width;
radTexture->height = height;
radTexture->depth = depth;
radTexture->samples = samples;
GLenum format = GL_NONE;
GLenum type = GL_NONE;
switch(internalFormat)
{
case RAD_RGBA8:
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
break;
case RAD_DEPTH24_STENCIL8:
format = GL_DEPTH_STENCIL_OES;
type = GL_UNSIGNED_INT_24_8_OES;
break;
default:
UNIMPLEMENTED(); // FIXME
}
switch(target)
{
case RAD_TEXTURE_2D:
{
es2::Texture2D *tex = new es2::Texture2D();
for(int level = 0; level < levels; level++)
{
tex->setImage(level, width >> level, height >> level, format, type, 1, nullptr);
}
tex->addRef();
radTexture->texture = tex;
}
break;
default:
UNIMPLEMENTED(); // FIXME
}
}
RADtextureHandle RADAPIENTRY radGetTextureSamplerHandle(RADtexture texture, RADsampler sampler, RADtextureTarget target, RADinternalFormat internalFormat, RADuint minLevel, RADuint numLevels, RADuint minLayer, RADuint numLayers)
{
rad::Texture *radTexture = reinterpret_cast<rad::Texture*>(texture);
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
rad::TextureSampler *textureSampler = new rad::TextureSampler(radTexture, radSampler, target, internalFormat, minLevel, numLevels, minLayer, numLayers);
radTexture->textureSamplers.push_back(textureSampler); // FIXME: Check for matching existing textureSampler
return reinterpret_cast<RADtextureHandle>(textureSampler);
}
RADrenderTargetHandle RADAPIENTRY radGetTextureRenderTargetHandle(RADtexture texture, RADtextureTarget target, RADinternalFormat internalFormat, RADuint level, RADuint minLayer, RADuint numLayers)
{
rad::Texture *radTexture = reinterpret_cast<rad::Texture*>(texture);
ASSERT(radTexture->texture);
ASSERT(radTexture->internalFormat == internalFormat);
ASSERT(minLayer == 0);
ASSERT(numLayers == 1);
GLenum glTarget = GL_NONE;
switch(target)
{
case RAD_TEXTURE_2D:
glTarget = GL_TEXTURE_2D;
break;
default:
UNREACHABLE();
}
egl::Image *image = radTexture->texture->getRenderTarget(glTarget, level);
image->release(); // FIXME: Handles are weak pointers
return reinterpret_cast<RADrenderTargetHandle>(image);
}
RADsampler RADAPIENTRY radCreateSampler(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::Sampler *sampler = new rad::Sampler(radDevice);
return reinterpret_cast<RADsampler>(sampler);
}
void RADAPIENTRY radReferenceSampler(RADsampler sampler)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->reference();
}
void RADAPIENTRY radReleaseSampler(RADsampler sampler)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->release();
}
void RADAPIENTRY radSamplerDefault(RADsampler sampler)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->defaults();
}
void RADAPIENTRY radSamplerMinMagFilter(RADsampler sampler, RADminFilter min, RADmagFilter mag)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->minFilter = min;
radSampler->magFilter = mag;
}
void RADAPIENTRY radSamplerWrapMode(RADsampler sampler, RADwrapMode s, RADwrapMode t, RADwrapMode r)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->wrapModeS = s;
radSampler->wrapModeT = t;
radSampler->wrapModeR = r;
}
void RADAPIENTRY radSamplerLodClamp(RADsampler sampler, RADfloat min, RADfloat max)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->minLod = min;
radSampler->maxLod = max;
}
void RADAPIENTRY radSamplerLodBias(RADsampler sampler, RADfloat bias)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->lodBias = bias;
}
void RADAPIENTRY radSamplerCompare(RADsampler sampler, RADcompareMode mode, RADcompareFunc func)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->compareMode = mode;
radSampler->compareFunc = func;
}
void RADAPIENTRY radSamplerBorderColorFloat(RADsampler sampler, const RADfloat *borderColor)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->borderColor[0] = borderColor[0];
radSampler->borderColor[1] = borderColor[1];
radSampler->borderColor[2] = borderColor[2];
radSampler->borderColor[3] = borderColor[3];
}
void RADAPIENTRY radSamplerBorderColorInt(RADsampler sampler, const RADuint *borderColor)
{
rad::Sampler *radSampler = reinterpret_cast<rad::Sampler*>(sampler);
radSampler->borderColorInt[0] = borderColor[0];
radSampler->borderColorInt[1] = borderColor[1];
radSampler->borderColorInt[2] = borderColor[2];
radSampler->borderColorInt[3] = borderColor[3];
}
RADcolorState RADAPIENTRY radCreateColorState(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::ColorState *colorState = new rad::ColorState(radDevice);
return reinterpret_cast<RADcolorState>(colorState);
}
void RADAPIENTRY radReferenceColorState(RADcolorState color)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->reference();
}
void RADAPIENTRY radReleaseColorState(RADcolorState color)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->release();
}
void RADAPIENTRY radColorDefault(RADcolorState color)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->defaults();
}
void RADAPIENTRY radColorBlendEnable(RADcolorState color, RADuint index, RADboolean enable)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->blend[index].enable = enable;
}
void RADAPIENTRY radColorBlendFunc(RADcolorState color, RADuint index, RADblendFunc srcFunc, RADblendFunc dstFunc, RADblendFunc srcFuncAlpha, RADblendFunc dstFuncAlpha)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->blend[index].srcFunc = srcFunc;
colorState->blend[index].dstFunc = dstFunc;
colorState->blend[index].srcFuncAlpha = srcFuncAlpha;
colorState->blend[index].dstFuncAlpha = dstFuncAlpha;
}
void RADAPIENTRY radColorBlendEquation(RADcolorState color, RADuint index, RADblendEquation modeRGB, RADblendEquation modeAlpha)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->blend[index].modeRGB = modeRGB;
colorState->blend[index].modeAlpha = modeAlpha;
}
void RADAPIENTRY radColorMask(RADcolorState color, RADuint index, RADboolean r, RADboolean g, RADboolean b, RADboolean a)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->blend[index].maskRGBA[0] = r;
colorState->blend[index].maskRGBA[1] = g;
colorState->blend[index].maskRGBA[2] = b;
colorState->blend[index].maskRGBA[3] = a;
}
void RADAPIENTRY radColorNumTargets(RADcolorState color, RADuint numTargets)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->numTargets = numTargets;
}
void RADAPIENTRY radColorLogicOpEnable(RADcolorState color, RADboolean enable)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->logicOpEnable = enable;
}
void RADAPIENTRY radColorLogicOp(RADcolorState color, RADlogicOp logicOp)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->logicOp = logicOp;
}
void RADAPIENTRY radColorAlphaToCoverageEnable(RADcolorState color, RADboolean enable)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->alphaToCoverageEnable = enable;
}
void RADAPIENTRY radColorBlendColor(RADcolorState color, const RADfloat *blendColor)
{
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
colorState->blendColor[0] = blendColor[0];
colorState->blendColor[1] = blendColor[1];
colorState->blendColor[2] = blendColor[2];
colorState->blendColor[3] = blendColor[3];
}
void RADAPIENTRY radColorDynamic(RADcolorState color, RADcolorDynamic dynamic, RADboolean enable) {UNIMPLEMENTED();}
RADrasterState RADAPIENTRY radCreateRasterState(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::RasterState *rasterState = new rad::RasterState(radDevice);
return reinterpret_cast<RADrasterState>(rasterState);
}
void RADAPIENTRY radReferenceRasterState(RADrasterState raster)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->reference();
}
void RADAPIENTRY radReleaseRasterState(RADrasterState raster)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->release();
}
void RADAPIENTRY radRasterDefault(RADrasterState raster)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->defaults();
}
void RADAPIENTRY radRasterPointSize(RADrasterState raster, RADfloat pointSize)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->pointSize = pointSize;
}
void RADAPIENTRY radRasterLineWidth(RADrasterState raster, RADfloat lineWidth)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->lineWidth = lineWidth;
}
void RADAPIENTRY radRasterCullFace(RADrasterState raster, RADfaceBitfield face)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->cullFace = face;
}
void RADAPIENTRY radRasterFrontFace(RADrasterState raster, RADfrontFace face)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->frontFace = face;
}
void RADAPIENTRY radRasterPolygonMode(RADrasterState raster, RADpolygonMode polygonMode)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->polygonMode = polygonMode;
}
void RADAPIENTRY radRasterPolygonOffsetClamp(RADrasterState raster, RADfloat factor, RADfloat units, RADfloat clamp)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->offsetFactor = factor;
rasterState->offsetUnits = units;
rasterState->offsetClamp = clamp;
}
void RADAPIENTRY radRasterPolygonOffsetEnables(RADrasterState raster, RADpolygonOffsetEnables enables)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->polygonOffsetEnables = enables;
}
void RADAPIENTRY radRasterDiscardEnable(RADrasterState raster, RADboolean enable)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->discardEnable = enable;
}
void RADAPIENTRY radRasterMultisampleEnable(RADrasterState raster, RADboolean enable)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->multisampleEnable = enable;
}
void RADAPIENTRY radRasterSamples(RADrasterState raster, RADuint samples)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->samples = samples;
}
void RADAPIENTRY radRasterSampleMask(RADrasterState raster, RADuint mask)
{
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
rasterState->sampleMask = mask;
}
void RADAPIENTRY radRasterDynamic(RADrasterState raster, RADrasterDynamic dynamic, RADboolean enable)
{
UNIMPLEMENTED();
}
RADdepthStencilState RADAPIENTRY radCreateDepthStencilState(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::DepthStencilState *depthStencilState = new rad::DepthStencilState(radDevice);
return reinterpret_cast<RADdepthStencilState>(depthStencilState);
}
void RADAPIENTRY radReferenceDepthStencilState(RADdepthStencilState depthStencil)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
depthStencilState->reference();
}
void RADAPIENTRY radReleaseDepthStencilState(RADdepthStencilState depthStencil)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
depthStencilState->release();
}
void RADAPIENTRY radDepthStencilDefault(RADdepthStencilState depthStencil)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
depthStencilState->defaults();
}
void RADAPIENTRY radDepthStencilDepthTestEnable(RADdepthStencilState depthStencil, RADboolean enable)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
depthStencilState->depthTestEnable = enable;
}
void RADAPIENTRY radDepthStencilDepthWriteEnable(RADdepthStencilState depthStencil, RADboolean enable)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
depthStencilState->depthWriteEnable = enable;
}
void RADAPIENTRY radDepthStencilDepthFunc(RADdepthStencilState depthStencil, RADdepthFunc func)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
depthStencilState->depthFunc = func;
}
void RADAPIENTRY radDepthStencilStencilTestEnable(RADdepthStencilState depthStencil, RADboolean enable)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
depthStencilState->stencilTestEnable = enable;
}
void RADAPIENTRY radDepthStencilStencilFunc(RADdepthStencilState depthStencil, RADfaceBitfield faces, RADstencilFunc func, RADint ref, RADuint mask)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
if(faces & RAD_FACE_FRONT)
{
depthStencilState->stencilFuncFront = func;
depthStencilState->stencilRefFront = ref;
depthStencilState->stencilMaskFront = mask;
}
if(faces & RAD_FACE_BACK)
{
depthStencilState->stencilFuncBack = func;
depthStencilState->stencilRefBack = ref;
depthStencilState->stencilMaskBack = mask;
}
}
void RADAPIENTRY radDepthStencilStencilOp(RADdepthStencilState depthStencil, RADfaceBitfield faces, RADstencilOp fail, RADstencilOp depthFail, RADstencilOp depthPass)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
if(faces & RAD_FACE_FRONT)
{
depthStencilState->stencilFailOpFront = fail;
depthStencilState->depthFailOpFront = depthFail;
depthStencilState->depthPassOpFront = depthPass;
}
if(faces & RAD_FACE_BACK)
{
depthStencilState->stencilFailOpBack = fail;
depthStencilState->depthFailOpBack = depthFail;
depthStencilState->depthPassOpBack = depthPass;
}
}
void RADAPIENTRY radDepthStencilStencilMask(RADdepthStencilState depthStencil, RADfaceBitfield faces, RADuint mask)
{
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
if(faces & RAD_FACE_FRONT)
{
depthStencilState->stencilMaskFront = mask;
}
if(faces & RAD_FACE_BACK)
{
depthStencilState->stencilMaskBack = mask;
}
}
void RADAPIENTRY radDepthStencilDynamic(RADdepthStencilState depthStencil, RADdepthStencilDynamic dynamic, RADboolean enable)
{
UNIMPLEMENTED();
}
RADvertexState RADAPIENTRY radCreateVertexState(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::VertexState *vertexState = new rad::VertexState(radDevice);
return reinterpret_cast<RADvertexState>(vertexState);
}
void RADAPIENTRY radReferenceVertexState(RADvertexState vertex)
{
rad::VertexState *vertexState = reinterpret_cast<rad::VertexState*>(vertex);
vertexState->reference();
}
void RADAPIENTRY radReleaseVertexState(RADvertexState vertex)
{
rad::VertexState *vertexState = reinterpret_cast<rad::VertexState*>(vertex);
vertexState->release();
}
void RADAPIENTRY radVertexDefault(RADvertexState vertex) {UNIMPLEMENTED();}
void RADAPIENTRY radVertexAttribFormat(RADvertexState vertex, RADint attribIndex, RADint numComponents, RADint bytesPerComponent, RADattribType type, RADuint relativeOffset)
{
ASSERT(attribIndex >= 0 && attribIndex < GL_MAX_VERTEX_ATTRIBS);
rad::VertexState *vertexState = reinterpret_cast<rad::VertexState*>(vertex);
vertexState->attrib[attribIndex].numComponents = numComponents;
vertexState->attrib[attribIndex].bytesPerComponent = bytesPerComponent;
vertexState->attrib[attribIndex].type = type;
vertexState->attrib[attribIndex].relativeOffset = relativeOffset;
}
void RADAPIENTRY radVertexAttribBinding(RADvertexState vertex, RADint attribIndex, RADint bindingIndex)
{
ASSERT(attribIndex >= 0 && attribIndex < GL_MAX_VERTEX_ATTRIBS);
rad::VertexState *vertexState = reinterpret_cast<rad::VertexState*>(vertex);
vertexState->attrib[attribIndex].bindingIndex = bindingIndex;
}
void RADAPIENTRY radVertexBindingGroup(RADvertexState vertex, RADint bindingIndex, RADint group, RADint index)
{
ASSERT(bindingIndex >= 0 && bindingIndex < GL_MAX_VERTEX_ATTRIBS);
rad::VertexState *vertexState = reinterpret_cast<rad::VertexState*>(vertex);
vertexState->binding[bindingIndex].group = group;
vertexState->binding[bindingIndex].index = index;
}
void RADAPIENTRY radVertexAttribEnable(RADvertexState vertex, RADint attribIndex, RADboolean enable)
{
ASSERT(attribIndex >= 0 && attribIndex < GL_MAX_VERTEX_ATTRIBS);
rad::VertexState *vertexState = reinterpret_cast<rad::VertexState*>(vertex);
vertexState->attrib[attribIndex].bindingIndex = enable;
}
void RADAPIENTRY radVertexBindingStride(RADvertexState vertex, RADint bindingIndex, RADuint stride)
{
ASSERT(bindingIndex >= 0 && bindingIndex < GL_MAX_VERTEX_ATTRIBS);
rad::VertexState *vertexState = reinterpret_cast<rad::VertexState*>(vertex);
vertexState->binding[bindingIndex].stride = stride;
}
RADrtFormatState RADAPIENTRY radCreateRtFormatState(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::FormatState *formatState = new rad::FormatState(radDevice);
return reinterpret_cast<RADrtFormatState>(formatState);
}
void RADAPIENTRY radReferenceRtFormatState(RADrtFormatState rtFormat)
{
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
formatState->reference();
}
void RADAPIENTRY radReleaseRtFormatState(RADrtFormatState rtFormat)
{
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
formatState->release();
}
void RADAPIENTRY radRtFormatDefault(RADrtFormatState rtFormat)
{
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
formatState->defaults();
}
void RADAPIENTRY radRtFormatColorFormat(RADrtFormatState rtFormat, RADuint index, RADinternalFormat format)
{
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
formatState->colorFormat[index] = format;
}
void RADAPIENTRY radRtFormatDepthFormat(RADrtFormatState rtFormat, RADinternalFormat format)
{
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
formatState->depthFormat = format;
}
void RADAPIENTRY radRtFormatStencilFormat(RADrtFormatState rtFormat, RADinternalFormat format)
{
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
formatState->stencilFormat = format;
}
void RADAPIENTRY radRtFormatColorSamples(RADrtFormatState rtFormat, RADuint samples)
{
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
formatState->colorSamples = samples;
}
void RADAPIENTRY radRtFormatDepthStencilSamples(RADrtFormatState rtFormat, RADuint samples)
{
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
formatState->depthStencilSamples = samples;
}
RADpipeline RADAPIENTRY radCreatePipeline(RADdevice device, RADpipelineType pipelineType)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::Pipeline *pipeline = new rad::Pipeline(radDevice);
return reinterpret_cast<RADpipeline>(pipeline);
}
void RADAPIENTRY radReferencePipeline(RADpipeline pipeline)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
radPipeline->reference();
}
void RADAPIENTRY radReleasePipeline(RADpipeline pipeline)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
radPipeline->release();
}
void RADAPIENTRY radPipelineProgramStages(RADpipeline pipeline, RADbitfield stages, RADprogram program)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
rad::Program *radProgram = reinterpret_cast<rad::Program*>(program);
if(stages & RAD_VERTEX_SHADER_BIT)
{
ASSERT(!radPipeline->vertexProgram);
radProgram->reference(); // FIXME: here or at compile?
radPipeline->vertexProgram = radProgram;
}
if(stages & RAD_FRAGMENT_SHADER_BIT)
{
ASSERT(!radPipeline->fragmentProgram);
radProgram->reference(); // FIXME: here or at compile?
radPipeline->fragmentProgram = radProgram;
}
}
void RADAPIENTRY radPipelineVertexState(RADpipeline pipeline, RADvertexState vertex)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
rad::VertexState *vertexState = reinterpret_cast<rad::VertexState*>(vertex);
ASSERT(!radPipeline->vertexState);
vertexState->reference(); // FIXME: here or at compile?
radPipeline->vertexState = vertexState;
}
void RADAPIENTRY radPipelineColorState(RADpipeline pipeline, RADcolorState color)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
rad::ColorState *colorState = reinterpret_cast<rad::ColorState*>(color);
ASSERT(!radPipeline->colorState);
colorState->reference(); // FIXME: here or at compile?
radPipeline->colorState = colorState;
}
void RADAPIENTRY radPipelineRasterState(RADpipeline pipeline, RADrasterState raster)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
rad::RasterState *rasterState = reinterpret_cast<rad::RasterState*>(raster);
ASSERT(!radPipeline->rasterState);
rasterState->reference(); // FIXME: here or at compile?
radPipeline->rasterState = rasterState;
}
void RADAPIENTRY radPipelineDepthStencilState(RADpipeline pipeline, RADdepthStencilState depthStencil)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
rad::DepthStencilState *depthStencilState = reinterpret_cast<rad::DepthStencilState*>(depthStencil);
ASSERT(!radPipeline->depthStencilState);
depthStencilState->reference(); // FIXME: here or at compile?
radPipeline->depthStencilState = depthStencilState;
}
void RADAPIENTRY radPipelineRtFormatState(RADpipeline pipeline, RADrtFormatState rtFormat)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
rad::FormatState *formatState = reinterpret_cast<rad::FormatState*>(rtFormat);
ASSERT(!radPipeline->formatState);
formatState->reference(); // FIXME: here or at compile?
radPipeline->formatState = formatState;
}
void RADAPIENTRY radPipelinePrimitiveType(RADpipeline pipeline, RADprimitiveType mode)
{
rad::Pipeline *radPipeline = reinterpret_cast<rad::Pipeline*>(pipeline);
radPipeline->primitiveType = mode;
}
void RADAPIENTRY radCompilePipeline(RADpipeline pipeline)
{
// FIXME: Reference state objects here or when set?
return;
}
RADpipelineHandle RADAPIENTRY radGetPipelineHandle(RADpipeline pipeline)
{
return reinterpret_cast<RADpipelineHandle>(pipeline);
}
RADcommandBuffer RADAPIENTRY radCreateCommandBuffer(RADdevice device, RADqueueType queueType)
{
return 0;
}
void RADAPIENTRY radReferenceCommandBuffer(RADcommandBuffer cmdBuf) {UNIMPLEMENTED();}
void RADAPIENTRY radReleaseCommandBuffer(RADcommandBuffer cmdBuf)
{
return;
}
void RADAPIENTRY radCmdBindPipeline(RADcommandBuffer cmdBuf, RADpipelineType pipelineType, RADpipelineHandle pipelineHandle)
{
return;
}
void RADAPIENTRY radCmdBindGroup(RADcommandBuffer cmdBuf, RADbitfield stages, RADuint group, RADuint count, RADbindGroupHandle groupHandle, RADuint offset)
{
}
void RADAPIENTRY radCmdDrawArrays(RADcommandBuffer cmdBuf, RADprimitiveType mode, RADint first, RADsizei count) {UNIMPLEMENTED();}
void RADAPIENTRY radCmdDrawElements(RADcommandBuffer cmdBuf, RADprimitiveType mode, RADindexType type, RADsizei count, RADindexHandle indexHandle, RADuint offset)
{
return;
}
RADboolean RADAPIENTRY radCompileCommandBuffer(RADcommandBuffer cmdBuf)
{
return false;
}
RADcommandHandle RADAPIENTRY radGetCommandHandle(RADcommandBuffer cmdBuf)
{
return 0;
}
void RADAPIENTRY radCmdStencilValueMask(RADcommandBuffer cmdBuf, RADfaceBitfield faces, RADuint mask) {UNIMPLEMENTED();}
void RADAPIENTRY radCmdStencilMask(RADcommandBuffer cmdBuf, RADfaceBitfield faces, RADuint mask) {UNIMPLEMENTED();}
void RADAPIENTRY radCmdStencilRef(RADcommandBuffer cmdBuf, RADfaceBitfield faces, RADint ref) {UNIMPLEMENTED();}
void RADAPIENTRY radCmdBlendColor(RADcommandBuffer cmdBuf, const RADfloat *blendColor) {UNIMPLEMENTED();}
void RADAPIENTRY radCmdPointSize(RADcommandBuffer cmdBuf, RADfloat pointSize) {UNIMPLEMENTED();}
void RADAPIENTRY radCmdLineWidth(RADcommandBuffer cmdBuf, RADfloat lineWidth) {UNIMPLEMENTED();}
void RADAPIENTRY radCmdPolygonOffsetClamp(RADcommandBuffer cmdBuf, RADfloat factor, RADfloat units, RADfloat clamp) {UNIMPLEMENTED();}
void RADAPIENTRY radCmdSampleMask(RADcommandBuffer cmdBuf, RADuint mask) {UNIMPLEMENTED();}
RADpass RADAPIENTRY radCreatePass(RADdevice device)
{
rad::Device *radDevice = reinterpret_cast<rad::Device*>(device);
rad::Pass *pass = new rad::Pass(radDevice);
return reinterpret_cast<RADpass>(pass);
}
void RADAPIENTRY radReferencePass(RADpass pass)
{
rad::Pass *radPass = reinterpret_cast<rad::Pass*>(pass);
radPass->reference();
}
void RADAPIENTRY radReleasePass(RADpass pass)
{
rad::Pass *radPass = reinterpret_cast<rad::Pass*>(pass);
radPass->release();
}
void RADAPIENTRY radPassDefault(RADpass pass)
{
rad::Pass *radPass = reinterpret_cast<rad::Pass*>(pass);
radPass->defaults();
}
void RADAPIENTRY radCompilePass(RADpass pass)
{
return;
}
void RADAPIENTRY radPassRenderTargets(RADpass pass, RADuint numColors, const RADrenderTargetHandle *colors, RADrenderTargetHandle depth, RADrenderTargetHandle stencil)
{
rad::Pass *radPass = reinterpret_cast<rad::Pass*>(pass);
radPass->numColors = numColors;
for(unsigned int i = 0; i < numColors; i++)
{
ASSERT(colors[i]);
es2::Image *colorTarget = reinterpret_cast<es2::Image*>(colors[i]);
colorTarget->addRef(); // FIXME: here or at compile?
radPass->colorTarget[i] = colorTarget;
}
if(depth)
{
es2::Image *depthTarget = reinterpret_cast<es2::Image*>(depth);
depthTarget->addRef(); // FIXME: here or at compile?
radPass->depthTarget = depthTarget;
}
if(stencil)
{
es2::Image *stencilTarget = reinterpret_cast<es2::Image*>(stencil);
stencilTarget->addRef(); // FIXME: here or at compile?
radPass->stencilTarget = stencilTarget;
}
}
void RADAPIENTRY radPassPreserveEnable(RADpass pass, RADrtAttachment attachment, RADboolean enable) {UNIMPLEMENTED();}
void RADAPIENTRY radPassDiscard(RADpass pass, RADuint numTextures, const RADtexture *textures, const RADoffset2D *offsets) {UNIMPLEMENTED();}
void RADAPIENTRY radPassResolve(RADpass pass, RADrtAttachment attachment, RADtexture texture)
{
return;
}
void RADAPIENTRY radPassStore(RADpass pass, RADuint numTextures, const RADtexture *textures, const RADoffset2D *offsets) {UNIMPLEMENTED();}
void RADAPIENTRY radPassClip(RADpass pass, const RADrect2D *rect) {UNIMPLEMENTED();}
void RADAPIENTRY radPassDependencies(RADpass pass, RADuint numPasses, const RADpass *otherPasses, const RADbitfield *srcMask, const RADbitfield *dstMask, const RADbitfield *flushMask, const RADbitfield *invalidateMask) {UNIMPLEMENTED();}
void RADAPIENTRY radPassTilingBoundary(RADpass pass, RADboolean boundary) {UNIMPLEMENTED();}
void RADAPIENTRY radPassTileFilterWidth(RADpass pass, RADuint filterWidth, RADuint filterHeight) {UNIMPLEMENTED();}
void RADAPIENTRY radPassTileFootprint(RADpass pass, RADuint bytesPerPixel, RADuint maxFilterWidth, RADuint maxFilterHeight) {UNIMPLEMENTED();}
RADsync RADAPIENTRY radCreateSync(RADdevice device)
{
return 0;
}
void RADAPIENTRY radReferenceSync(RADsync sync) {UNIMPLEMENTED();}
void RADAPIENTRY radReleaseSync(RADsync sync)
{
return;
}
void RADAPIENTRY radQueueFenceSync(RADqueue queue, RADsync sync, RADsyncCondition condition, RADbitfield flags)
{
return;
}
RADwaitSyncResult RADAPIENTRY radWaitSync(RADsync sync, RADuint64 timeout) {UNIMPLEMENTED(); return RAD_WAIT_SYNC_FAILED;}
RADboolean RADAPIENTRY radQueueWaitSync(RADqueue queue, RADsync sync)
{
return 0;
}
RADPROC RADAPIENTRY radGetProcAddress(const RADchar *procname)
{
struct Extension
{
const char *name;
RADPROC address;
};
static const Extension glExtensions[] =
{
#define EXTENSION(name) {#name, (RADPROC)name}
EXTENSION(radGetProcAddress),
EXTENSION(radCreateDevice),
EXTENSION(radReferenceDevice),
EXTENSION(radReleaseDevice),
EXTENSION(radGetTokenHeader),
EXTENSION(radCreateQueue),
EXTENSION(radReferenceQueue),
EXTENSION(radReleaseQueue),
EXTENSION(radQueueTagBuffer),
EXTENSION(radQueueTagTexture),
EXTENSION(radQueueSubmitCommands),
EXTENSION(radFlushQueue),
EXTENSION(radFinishQueue),
EXTENSION(radQueueViewport),
EXTENSION(radQueueScissor),
EXTENSION(radQueueCopyBufferToImage),
EXTENSION(radQueueCopyImageToBuffer),
EXTENSION(radQueueCopyBuffer),
EXTENSION(radQueueClearColor),
EXTENSION(radQueueClearDepth),
EXTENSION(radQueueClearStencil),
EXTENSION(radQueuePresent),
EXTENSION(radQueueDrawArrays),
EXTENSION(radQueueDrawElements),
EXTENSION(radQueueBindPipeline),
EXTENSION(radQueueBindGroup),
EXTENSION(radQueueBeginPass),
EXTENSION(radQueueEndPass),
EXTENSION(radQueueSubmitDynamic),
EXTENSION(radQueueStencilValueMask),
EXTENSION(radQueueStencilMask),
EXTENSION(radQueueStencilRef),
EXTENSION(radQueueBlendColor),
EXTENSION(radQueuePointSize),
EXTENSION(radQueueLineWidth),
EXTENSION(radQueuePolygonOffsetClamp),
EXTENSION(radQueueSampleMask),
EXTENSION(radCreateProgram),
EXTENSION(radReferenceProgram),
EXTENSION(radReleaseProgram),
EXTENSION(radProgramSource),
EXTENSION(radCreateBuffer),
EXTENSION(radReferenceBuffer),
EXTENSION(radReleaseBuffer),
EXTENSION(radBufferAccess),
EXTENSION(radBufferMapAccess),
EXTENSION(radBufferStorage),
EXTENSION(radMapBuffer),
EXTENSION(radGetVertexHandle),
EXTENSION(radGetIndexHandle),
EXTENSION(radGetUniformHandle),
EXTENSION(radGetBindGroupHandle),
EXTENSION(radCreateTexture),
EXTENSION(radReferenceTexture),
EXTENSION(radReleaseTexture),
EXTENSION(radTextureAccess),
EXTENSION(radTextureStorage),
EXTENSION(radGetTextureSamplerHandle),
EXTENSION(radGetTextureRenderTargetHandle),
EXTENSION(radCreateSampler),
EXTENSION(radReferenceSampler),
EXTENSION(radReleaseSampler),
EXTENSION(radSamplerDefault),
EXTENSION(radSamplerMinMagFilter),
EXTENSION(radSamplerWrapMode),
EXTENSION(radSamplerLodClamp),
EXTENSION(radSamplerLodBias),
EXTENSION(radSamplerCompare),
EXTENSION(radSamplerBorderColorFloat),
EXTENSION(radSamplerBorderColorInt),
EXTENSION(radCreateColorState),
EXTENSION(radReferenceColorState),
EXTENSION(radReleaseColorState),
EXTENSION(radColorDefault),
EXTENSION(radColorBlendEnable),
EXTENSION(radColorBlendFunc),
EXTENSION(radColorBlendEquation),
EXTENSION(radColorMask),
EXTENSION(radColorNumTargets),
EXTENSION(radColorLogicOpEnable),
EXTENSION(radColorLogicOp),
EXTENSION(radColorAlphaToCoverageEnable),
EXTENSION(radColorBlendColor),
EXTENSION(radColorDynamic),
EXTENSION(radCreateRasterState),
EXTENSION(radReferenceRasterState),
EXTENSION(radReleaseRasterState),
EXTENSION(radRasterDefault),
EXTENSION(radRasterPointSize),
EXTENSION(radRasterLineWidth),
EXTENSION(radRasterCullFace),
EXTENSION(radRasterFrontFace),
EXTENSION(radRasterPolygonMode),
EXTENSION(radRasterPolygonOffsetClamp),
EXTENSION(radRasterPolygonOffsetEnables),
EXTENSION(radRasterDiscardEnable),
EXTENSION(radRasterMultisampleEnable),
EXTENSION(radRasterSamples),
EXTENSION(radRasterSampleMask),
EXTENSION(radRasterDynamic),
EXTENSION(radCreateDepthStencilState),
EXTENSION(radReferenceDepthStencilState),
EXTENSION(radReleaseDepthStencilState),
EXTENSION(radDepthStencilDefault),
EXTENSION(radDepthStencilDepthTestEnable),
EXTENSION(radDepthStencilDepthWriteEnable),
EXTENSION(radDepthStencilDepthFunc),
EXTENSION(radDepthStencilStencilTestEnable),
EXTENSION(radDepthStencilStencilFunc),
EXTENSION(radDepthStencilStencilOp),
EXTENSION(radDepthStencilStencilMask),
EXTENSION(radDepthStencilDynamic),
EXTENSION(radCreateVertexState),
EXTENSION(radReferenceVertexState),
EXTENSION(radReleaseVertexState),
EXTENSION(radVertexDefault),
EXTENSION(radVertexAttribFormat),
EXTENSION(radVertexAttribBinding),
EXTENSION(radVertexBindingGroup),
EXTENSION(radVertexAttribEnable),
EXTENSION(radVertexBindingStride),
EXTENSION(radCreateRtFormatState),
EXTENSION(radReferenceRtFormatState),
EXTENSION(radReleaseRtFormatState),
EXTENSION(radRtFormatDefault),
EXTENSION(radRtFormatColorFormat),
EXTENSION(radRtFormatDepthFormat),
EXTENSION(radRtFormatStencilFormat),
EXTENSION(radRtFormatColorSamples),
EXTENSION(radRtFormatDepthStencilSamples),
EXTENSION(radCreatePipeline),
EXTENSION(radReferencePipeline),
EXTENSION(radReleasePipeline),
EXTENSION(radPipelineProgramStages),
EXTENSION(radPipelineVertexState),
EXTENSION(radPipelineColorState),
EXTENSION(radPipelineRasterState),
EXTENSION(radPipelineDepthStencilState),
EXTENSION(radPipelineRtFormatState),
EXTENSION(radPipelinePrimitiveType),
EXTENSION(radCompilePipeline),
EXTENSION(radGetPipelineHandle),
EXTENSION(radCreateCommandBuffer),
EXTENSION(radReferenceCommandBuffer),
EXTENSION(radReleaseCommandBuffer),
EXTENSION(radCmdBindPipeline),
EXTENSION(radCmdBindGroup),
EXTENSION(radCmdDrawArrays),
EXTENSION(radCmdDrawElements),
EXTENSION(radCompileCommandBuffer),
EXTENSION(radGetCommandHandle),
EXTENSION(radCmdStencilValueMask),
EXTENSION(radCmdStencilMask),
EXTENSION(radCmdStencilRef),
EXTENSION(radCmdBlendColor),
EXTENSION(radCmdPointSize),
EXTENSION(radCmdLineWidth),
EXTENSION(radCmdPolygonOffsetClamp),
EXTENSION(radCmdSampleMask),
EXTENSION(radCreatePass),
EXTENSION(radReferencePass),
EXTENSION(radReleasePass),
EXTENSION(radPassDefault),
EXTENSION(radCompilePass),
EXTENSION(radPassRenderTargets),
EXTENSION(radPassPreserveEnable),
EXTENSION(radPassDiscard),
EXTENSION(radPassResolve),
EXTENSION(radPassStore),
EXTENSION(radPassClip),
EXTENSION(radPassDependencies),
EXTENSION(radPassTilingBoundary),
EXTENSION(radPassTileFilterWidth),
EXTENSION(radPassTileFootprint),
EXTENSION(radCreateSync),
EXTENSION(radReferenceSync),
EXTENSION(radReleaseSync),
EXTENSION(radQueueFenceSync),
EXTENSION(radWaitSync),
EXTENSION(radQueueWaitSync),
#undef EXTENSION
};
for(int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
{
if(strcmp(procname, glExtensions[ext].name) == 0)
{
return (RADPROC)glExtensions[ext].address;
}
}
return NULL;
}
void GL_APIENTRY Register(const char *licenseKey)
{
RegisterLicenseKey(licenseKey);
}
}