Fix the error handling: only create one call unless there's an error and only check for errors in functions that can fail

This commit is contained in:
Magnus Norddahl 2019-12-20 03:39:06 +01:00
parent 4274ee2893
commit 80f815cad9
5 changed files with 218 additions and 252 deletions

View file

@ -64,16 +64,10 @@ namespace CodeImp.DoomBuilder.Rendering
public bool Disposed { get { return Handle == IntPtr.Zero; } }
public void ClearError()
void ThrowIfFailed(bool result)
{
RenderDevice_GetError(Handle);
}
private void CheckAndThrow()
{
string err = Marshal.PtrToStringAnsi(RenderDevice_GetError(Handle));
if (err != "")
throw new RenderDeviceException(err);
if (!result)
throw new RenderDeviceException(Marshal.PtrToStringAnsi(RenderDevice_GetError(Handle)));
}
public void Dispose()
@ -88,249 +82,208 @@ namespace CodeImp.DoomBuilder.Rendering
public void SetShader(ShaderName shader)
{
RenderDevice_SetShader(Handle, shader);
CheckAndThrow();
}
public void SetUniform(UniformName uniform, bool value)
{
RenderDevice_SetUniform(Handle, uniform, new float[] { value ? 1.0f : 0.0f }, 1);
CheckAndThrow();
}
public void SetUniform(UniformName uniform, float value)
{
RenderDevice_SetUniform(Handle, uniform, new float[] { value }, 1);
CheckAndThrow();
}
public void SetUniform(UniformName uniform, Vector2 value)
{
RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y }, 2);
CheckAndThrow();
}
public void SetUniform(UniformName uniform, Vector3 value)
{
RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z }, 3);
CheckAndThrow();
}
public void SetUniform(UniformName uniform, Vector4 value)
{
RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z, value.W }, 4);
CheckAndThrow();
}
public void SetUniform(UniformName uniform, Color4 value)
{
RenderDevice_SetUniform(Handle, uniform, new float[] { value.Red, value.Green, value.Blue, value.Alpha }, 4);
CheckAndThrow();
}
public void SetUniform(UniformName uniform, Matrix matrix)
{
RenderDevice_SetUniform(Handle, uniform, ref matrix, 16);
CheckAndThrow();
}
public void SetUniform(UniformName uniform, ref Matrix matrix)
{
RenderDevice_SetUniform(Handle, uniform, ref matrix, 16);
CheckAndThrow();
}
public void SetVertexBuffer(VertexBuffer buffer)
{
RenderDevice_SetVertexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero);
CheckAndThrow();
}
public void SetIndexBuffer(IndexBuffer buffer)
{
RenderDevice_SetIndexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero);
CheckAndThrow();
}
public void SetAlphaBlendEnable(bool value)
{
RenderDevice_SetAlphaBlendEnable(Handle, value);
CheckAndThrow();
}
public void SetAlphaTestEnable(bool value)
{
RenderDevice_SetAlphaTestEnable(Handle, value);
CheckAndThrow();
}
public void SetCullMode(Cull mode)
{
RenderDevice_SetCullMode(Handle, mode);
CheckAndThrow();
}
public void SetBlendOperation(BlendOperation op)
{
RenderDevice_SetBlendOperation(Handle, op);
CheckAndThrow();
}
public void SetSourceBlend(Blend blend)
{
RenderDevice_SetSourceBlend(Handle, blend);
CheckAndThrow();
}
public void SetDestinationBlend(Blend blend)
{
RenderDevice_SetDestinationBlend(Handle, blend);
CheckAndThrow();
}
public void SetFillMode(FillMode mode)
{
RenderDevice_SetFillMode(Handle, mode);
CheckAndThrow();
}
public void SetMultisampleAntialias(bool value)
{
RenderDevice_SetMultisampleAntialias(Handle, value);
CheckAndThrow();
}
public void SetZEnable(bool value)
{
RenderDevice_SetZEnable(Handle, value);
CheckAndThrow();
}
public void SetZWriteEnable(bool value)
{
RenderDevice_SetZWriteEnable(Handle, value);
CheckAndThrow();
}
public void SetTexture(BaseTexture value)
{
RenderDevice_SetTexture(Handle, value != null ? value.Handle : IntPtr.Zero);
CheckAndThrow();
}
public void SetSamplerFilter(TextureFilter filter)
{
SetSamplerFilter(filter, filter, TextureFilter.None, 0.0f);
CheckAndThrow();
}
public void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy)
{
RenderDevice_SetSamplerFilter(Handle, minfilter, magfilter, mipfilter, maxanisotropy);
CheckAndThrow();
}
public void SetSamplerState(TextureAddress address)
{
RenderDevice_SetSamplerState(Handle, address);
CheckAndThrow();
}
public void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount)
{
RenderDevice_DrawIndexed(Handle, type, startIndex, primitiveCount);
CheckAndThrow();
ThrowIfFailed(RenderDevice_DrawIndexed(Handle, type, startIndex, primitiveCount));
}
public void Draw(PrimitiveType type, int startIndex, int primitiveCount)
{
RenderDevice_Draw(Handle, type, startIndex, primitiveCount);
CheckAndThrow();
ThrowIfFailed(RenderDevice_Draw(Handle, type, startIndex, primitiveCount));
}
public void Draw(PrimitiveType type, int startIndex, int primitiveCount, FlatVertex[] data)
{
RenderDevice_DrawData(Handle, type, startIndex, primitiveCount, data);
CheckAndThrow();
ThrowIfFailed(RenderDevice_DrawData(Handle, type, startIndex, primitiveCount, data));
}
public void StartRendering(bool clear, Color4 backcolor)
{
RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), IntPtr.Zero, true);
CheckAndThrow();
ThrowIfFailed(RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), IntPtr.Zero, true));
}
public void StartRendering(bool clear, Color4 backcolor, Texture target, bool usedepthbuffer)
{
RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), target.Handle, usedepthbuffer);
CheckAndThrow();
ThrowIfFailed(RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), target.Handle, usedepthbuffer));
}
public void FinishRendering()
{
RenderDevice_FinishRendering(Handle);
CheckAndThrow();
ThrowIfFailed(RenderDevice_FinishRendering(Handle));
}
public void Present()
{
RenderDevice_Present(Handle);
CheckAndThrow();
ThrowIfFailed(RenderDevice_Present(Handle));
}
public void ClearTexture(Color4 backcolor, Texture texture)
{
RenderDevice_ClearTexture(Handle, backcolor.ToArgb(), texture.Handle);
CheckAndThrow();
ThrowIfFailed(RenderDevice_ClearTexture(Handle, backcolor.ToArgb(), texture.Handle));
}
public void CopyTexture(CubeTexture dst, CubeMapFace face)
{
RenderDevice_CopyTexture(Handle, dst.Handle, face);
CheckAndThrow();
ThrowIfFailed(RenderDevice_CopyTexture(Handle, dst.Handle, face));
}
public void SetBufferData(IndexBuffer buffer, int[] data)
{
RenderDevice_SetIndexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<int>());
CheckAndThrow();
ThrowIfFailed(RenderDevice_SetIndexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<int>()));
}
public void SetBufferData(VertexBuffer buffer, int length, VertexFormat format)
{
int stride = (format == VertexFormat.Flat) ? FlatVertex.Stride : WorldVertex.Stride;
RenderDevice_SetVertexBufferData(Handle, buffer.Handle, IntPtr.Zero, length * stride, format);
CheckAndThrow();
ThrowIfFailed(RenderDevice_SetVertexBufferData(Handle, buffer.Handle, IntPtr.Zero, length * stride, format));
}
public void SetBufferData(VertexBuffer buffer, FlatVertex[] data)
{
RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<FlatVertex>(), VertexFormat.Flat);
CheckAndThrow();
ThrowIfFailed(RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<FlatVertex>(), VertexFormat.Flat));
}
public void SetBufferData(VertexBuffer buffer, WorldVertex[] data)
{
RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<WorldVertex>(), VertexFormat.World);
CheckAndThrow();
ThrowIfFailed(RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<WorldVertex>(), VertexFormat.World));
}
public void SetBufferSubdata(VertexBuffer buffer, long destOffset, FlatVertex[] data)
{
RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * FlatVertex.Stride, data, data.Length * FlatVertex.Stride);
CheckAndThrow();
ThrowIfFailed(RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * FlatVertex.Stride, data, data.Length * FlatVertex.Stride));
}
public void SetBufferSubdata(VertexBuffer buffer, long destOffset, WorldVertex[] data)
{
RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * WorldVertex.Stride, data, data.Length * WorldVertex.Stride);
CheckAndThrow();
ThrowIfFailed(RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * WorldVertex.Stride, data, data.Length * WorldVertex.Stride));
}
public void SetBufferSubdata(VertexBuffer buffer, FlatVertex[] data, long size)
{
if (size < 0 || size > data.Length) throw new ArgumentOutOfRangeException("size");
RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, 0, data, size * FlatVertex.Stride);
CheckAndThrow();
ThrowIfFailed(RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, 0, data, size * FlatVertex.Stride));
}
public void SetPixels(Texture texture, System.Drawing.Bitmap bitmap)
@ -340,10 +293,14 @@ namespace CodeImp.DoomBuilder.Rendering
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
RenderDevice_SetPixels(Handle, texture.Handle, bmpdata.Scan0);
try
{
ThrowIfFailed(RenderDevice_SetPixels(Handle, texture.Handle, bmpdata.Scan0));
}
finally
{
bitmap.UnlockBits(bmpdata);
CheckAndThrow();
}
}
public void SetPixels(CubeTexture texture, CubeMapFace face, System.Drawing.Bitmap bitmap)
@ -353,29 +310,31 @@ namespace CodeImp.DoomBuilder.Rendering
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
RenderDevice_SetCubePixels(Handle, texture.Handle, face, bmpdata.Scan0);
try
{
ThrowIfFailed(RenderDevice_SetCubePixels(Handle, texture.Handle, face, bmpdata.Scan0));
}
finally
{
bitmap.UnlockBits(bmpdata);
CheckAndThrow();
}
}
public unsafe void SetPixels(Texture texture, uint* pixeldata)
{
RenderDevice_SetPixels(Handle, texture.Handle, new IntPtr(pixeldata));
CheckAndThrow();
ThrowIfFailed(RenderDevice_SetPixels(Handle, texture.Handle, new IntPtr(pixeldata)));
}
public unsafe void* MapPBO(Texture texture)
{
void* ptr = RenderDevice_MapPBO(Handle, texture.Handle).ToPointer();
CheckAndThrow();
ThrowIfFailed(ptr != null);
return ptr;
}
public void UnmapPBO(Texture texture)
{
RenderDevice_UnmapPBO(Handle, texture.Handle);
CheckAndThrow();
ThrowIfFailed(RenderDevice_UnmapPBO(Handle, texture.Handle));
}
internal void RegisterResource(IRenderResource res)
@ -427,13 +386,13 @@ namespace CodeImp.DoomBuilder.Rendering
static extern IntPtr RenderDevice_GetError(IntPtr handle);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr RenderDevice_SetShader(IntPtr handle, ShaderName name);
static extern bool RenderDevice_SetShader(IntPtr handle, ShaderName name);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count);
static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr RenderDevice_SetUniform(IntPtr handle, UniformName name, ref Matrix data, int count);
static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, ref Matrix data, int count);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetVertexBuffer(IntPtr handle, IntPtr buffer);
@ -481,61 +440,58 @@ namespace CodeImp.DoomBuilder.Rendering
static extern void RenderDevice_SetSamplerState(IntPtr handle, TextureAddress address);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_Draw(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount);
static extern bool RenderDevice_Draw(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_DrawIndexed(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount);
static extern bool RenderDevice_DrawIndexed(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_DrawData(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount, FlatVertex[] data);
static extern bool RenderDevice_DrawData(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount, FlatVertex[] data);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_StartRendering(IntPtr handle, bool clear, int backcolor);
static extern bool RenderDevice_StartRendering(IntPtr handle, bool clear, int backcolor, IntPtr target, bool usedepthbuffer);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_StartRendering(IntPtr handle, bool clear, int backcolor, IntPtr target, bool usedepthbuffer);
static extern bool RenderDevice_FinishRendering(IntPtr handle);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_FinishRendering(IntPtr handle);
static extern bool RenderDevice_Present(IntPtr handle);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_Present(IntPtr handle);
static extern bool RenderDevice_ClearTexture(IntPtr handle, int backcolor, IntPtr texture);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_ClearTexture(IntPtr handle, int backcolor, IntPtr texture);
static extern bool RenderDevice_CopyTexture(IntPtr handle, IntPtr dst, CubeMapFace face);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_CopyTexture(IntPtr handle, IntPtr dst, CubeMapFace face);
static extern bool RenderDevice_SetIndexBufferData(IntPtr handle, IntPtr buffer, int[] data, long size);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetIndexBufferData(IntPtr handle, IntPtr buffer, int[] data, long size);
static extern bool RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, IntPtr data, long size, VertexFormat format);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, IntPtr data, long size, VertexFormat format);
static extern bool RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, FlatVertex[] data, long size, VertexFormat format);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, FlatVertex[] data, long size, VertexFormat format);
static extern bool RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, WorldVertex[] data, long size, VertexFormat format);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, WorldVertex[] data, long size, VertexFormat format);
static extern bool RenderDevice_SetVertexBufferSubdata(IntPtr handle, IntPtr buffer, long destOffset, FlatVertex[] data, long sizeInBytes);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetVertexBufferSubdata(IntPtr handle, IntPtr buffer, long destOffset, FlatVertex[] data, long sizeInBytes);
static extern bool RenderDevice_SetVertexBufferSubdata(IntPtr handle, IntPtr buffer, long destOffset, WorldVertex[] data, long sizeInBytes);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetVertexBufferSubdata(IntPtr handle, IntPtr buffer, long destOffset, WorldVertex[] data, long sizeInBytes);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
protected static extern void RenderDevice_SetPixels(IntPtr handle, IntPtr texture, IntPtr data);
protected static extern bool RenderDevice_SetPixels(IntPtr handle, IntPtr texture, IntPtr data);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
protected static extern IntPtr RenderDevice_MapPBO(IntPtr handle, IntPtr texture);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
protected static extern void RenderDevice_UnmapPBO(IntPtr handle, IntPtr texture);
protected static extern bool RenderDevice_UnmapPBO(IntPtr handle, IntPtr texture);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
protected static extern void RenderDevice_SetCubePixels(IntPtr handle, IntPtr texture, CubeMapFace face, IntPtr data);
protected static extern bool RenderDevice_SetCubePixels(IntPtr handle, IntPtr texture, CubeMapFace face, IntPtr data);
//mxd. Anisotropic filtering steps
public static readonly List<float> AF_STEPS = new List<float> { 1.0f, 2.0f, 4.0f, 8.0f, 16.0f };

View file

@ -349,8 +349,6 @@ namespace CodeImp.DoomBuilder.Rendering
// Destroy rendertargets
DestroyRendertargets();
graphics.ClearError();
// Get new width and height
windowsize.Width = graphics.RenderTarget.ClientSize.Width;
windowsize.Height = graphics.RenderTarget.ClientSize.Height;

View file

@ -1,5 +1,7 @@
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <cstdint>
#include <vector>
#include <map>

View file

@ -49,9 +49,6 @@ RenderDevice::RenderDevice(void* disp, void* window)
DeclareUniform(UniformName::ignoreNormals, "ignoreNormals", UniformType::Float);
DeclareUniform(UniformName::spotLight, "spotLight", UniformType::Float);
memset(mLastError, 0, sizeof(mLastError));
memset(mReturnError, 0, sizeof(mReturnError));
Context = IOpenGLContext::Create(disp, window);
if (Context)
{
@ -303,35 +300,29 @@ void RenderDevice::SetSamplerState(TextureAddress address)
}
}
void RenderDevice::ApplyViewport()
{
glViewport(0, 0, mViewportWidth, mViewportHeight);
CheckGLError();
}
void RenderDevice::Draw(PrimitiveType type, int startIndex, int primitiveCount)
bool RenderDevice::Draw(PrimitiveType type, int startIndex, int primitiveCount)
{
static const int modes[] = { GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP };
static const int toVertexCount[] = { 2, 3, 1 };
static const int toVertexStart[] = { 0, 0, 2 };
if (mNeedApply) ApplyChanges();
if (mNeedApply && !ApplyChanges()) return false;
glDrawArrays(modes[(int)type], mVertexBufferStartIndex + startIndex, toVertexStart[(int)type] + primitiveCount * toVertexCount[(int)type]);
CheckGLError();
return CheckGLError();
}
void RenderDevice::DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount)
bool RenderDevice::DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount)
{
static const int modes[] = { GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP };
static const int toVertexCount[] = { 2, 3, 1 };
static const int toVertexStart[] = { 0, 0, 2 };
if (mNeedApply) ApplyChanges();
if (mNeedApply && !ApplyChanges()) return false;
glDrawElementsBaseVertex(modes[(int)type], toVertexStart[(int)type] + primitiveCount * toVertexCount[(int)type], GL_UNSIGNED_INT, (const void*)(startIndex * sizeof(uint32_t)), mVertexBufferStartIndex);
CheckGLError();
return CheckGLError();
}
void RenderDevice::DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data)
bool RenderDevice::DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data)
{
static const int modes[] = { GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP };
static const int toVertexCount[] = { 2, 3, 1 };
@ -339,17 +330,18 @@ void RenderDevice::DrawData(PrimitiveType type, int startIndex, int primitiveCou
int vertcount = toVertexStart[(int)type] + primitiveCount * toVertexCount[(int)type];
if (mNeedApply) ApplyChanges();
if (mNeedApply && !ApplyChanges()) return false;
glBindBuffer(GL_ARRAY_BUFFER, mStreamVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertcount * (size_t)SharedVertexBuffer::FlatStride, static_cast<const uint8_t*>(data) + startIndex * (size_t)SharedVertexBuffer::FlatStride, GL_STREAM_DRAW);
glBindVertexArray(mStreamVAO);
glDrawArrays(modes[(int)type], 0, vertcount);
ApplyVertexBuffer();
CheckGLError();
if (!CheckGLError()) return false;
return ApplyVertexBuffer();
}
void RenderDevice::StartRendering(bool clear, int backcolor, Texture* target, bool usedepthbuffer)
bool RenderDevice::StartRendering(bool clear, int backcolor, Texture* target, bool usedepthbuffer)
{
Context->MakeCurrent();
mContextIsCurrent = true;
@ -364,18 +356,19 @@ void RenderDevice::StartRendering(bool clear, int backcolor, Texture* target, bo
catch (std::runtime_error& e)
{
SetError("Error setting render target: %s", e.what());
return false;
}
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
mViewportWidth = target->GetWidth();
mViewportHeight = target->GetHeight();
ApplyViewport();
if (!ApplyViewport()) return false;
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
mViewportWidth = Context->GetWidth();
mViewportHeight = Context->GetHeight();
ApplyViewport();
if (!ApplyViewport()) return false;
}
if (clear && usedepthbuffer)
@ -402,29 +395,29 @@ void RenderDevice::StartRendering(bool clear, int backcolor, Texture* target, bo
mBlendStateChanged = true;
mRasterizerStateChanged = true;
CheckGLError();
return CheckGLError();
}
void RenderDevice::FinishRendering()
bool RenderDevice::FinishRendering()
{
Context->ClearCurrent();
mContextIsCurrent = false;
return true;
}
void RenderDevice::Present()
bool RenderDevice::Present()
{
Context->SwapBuffers();
CheckGLError();
return CheckGLError();
}
void RenderDevice::ClearTexture(int backcolor, Texture* texture)
bool RenderDevice::ClearTexture(int backcolor, Texture* texture)
{
StartRendering(true, backcolor, texture, false);
FinishRendering();
CheckGLError();
if (!StartRendering(true, backcolor, texture, false)) return false;
return FinishRendering();
}
void RenderDevice::CopyTexture(Texture* dst, CubeMapFace face)
bool RenderDevice::CopyTexture(Texture* dst, CubeMapFace face)
{
static const GLenum facegl[] = {
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
@ -445,11 +438,12 @@ void RenderDevice::CopyTexture(Texture* dst, CubeMapFace face)
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, oldTexture);
CheckGLError();
bool result = CheckGLError();
if (!mContextIsCurrent) Context->ClearCurrent();
return result;
}
void RenderDevice::SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t size, VertexFormat format)
bool RenderDevice::SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t size, VertexFormat format)
{
if (!mContextIsCurrent) Context->MakeCurrent();
@ -490,11 +484,12 @@ void RenderDevice::SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t
glBufferSubData(GL_ARRAY_BUFFER, buffer->BufferOffset, size, data);
glBindBuffer(GL_ARRAY_BUFFER, oldbinding);
CheckGLError();
bool result = CheckGLError();
if (!mContextIsCurrent) Context->ClearCurrent();
return result;
}
void RenderDevice::SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size)
bool RenderDevice::SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size)
{
if (!mContextIsCurrent) Context->MakeCurrent();
GLint oldbinding = 0;
@ -502,11 +497,12 @@ void RenderDevice::SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffs
glBindBuffer(GL_ARRAY_BUFFER, mSharedVertexBuffers[(int)buffer->Format]->GetBuffer());
glBufferSubData(GL_ARRAY_BUFFER, buffer->BufferOffset + destOffset, size, data);
glBindBuffer(GL_ARRAY_BUFFER, oldbinding);
CheckGLError();
bool result = CheckGLError();
if (!mContextIsCurrent) Context->ClearCurrent();
return result;
}
void RenderDevice::SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t size)
bool RenderDevice::SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t size)
{
if (!mContextIsCurrent) Context->MakeCurrent();
GLint oldbinding = 0;
@ -514,22 +510,21 @@ void RenderDevice::SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t s
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetBuffer());
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oldbinding);
CheckGLError();
bool result = CheckGLError();
if (!mContextIsCurrent) Context->ClearCurrent();
return result;
}
void RenderDevice::SetPixels(Texture* texture, const void* data)
bool RenderDevice::SetPixels(Texture* texture, const void* data)
{
texture->SetPixels(data);
InvalidateTexture(texture);
CheckGLError();
return InvalidateTexture(texture);
}
void RenderDevice::SetCubePixels(Texture* texture, CubeMapFace face, const void* data)
bool RenderDevice::SetCubePixels(Texture* texture, CubeMapFace face, const void* data)
{
texture->SetCubePixels(face, data);
InvalidateTexture(texture);
CheckGLError();
return InvalidateTexture(texture);
}
void* RenderDevice::MapPBO(Texture* texture)
@ -538,12 +533,17 @@ void* RenderDevice::MapPBO(Texture* texture)
GLint pbo = texture->GetPBO();
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
void* buf = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
CheckGLError();
bool result = CheckGLError();
if (!result && buf)
{
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
buf = nullptr;
}
if (!mContextIsCurrent) Context->ClearCurrent();
return buf;
}
void RenderDevice::UnmapPBO(Texture* texture)
bool RenderDevice::UnmapPBO(Texture* texture)
{
if (!mContextIsCurrent) Context->MakeCurrent();
GLint pbo = texture->GetPBO();
@ -551,35 +551,43 @@ void RenderDevice::UnmapPBO(Texture* texture)
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindTexture(GL_TEXTURE_2D, texture->GetTexture());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->GetWidth(), texture->GetHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
CheckGLError();
bool result = CheckGLError();
if (!mContextIsCurrent) Context->ClearCurrent();
mNeedApply = true;
mTexturesChanged = true;
return result;
}
void RenderDevice::InvalidateTexture(Texture* texture)
bool RenderDevice::InvalidateTexture(Texture* texture)
{
if (texture->IsTextureCreated())
{
if (!mContextIsCurrent) Context->MakeCurrent();
texture->Invalidate();
CheckGLError();
bool result = CheckGLError();
if (!mContextIsCurrent) Context->ClearCurrent();
mNeedApply = true;
mTexturesChanged = true;
return result;
}
else
{
return true;
}
}
bool RenderDevice::CheckGLError()
{
// on Windows, "no context" is a GL_INVALID_OPERATION error
GLenum error = glGetError();
if (error != GL_NO_ERROR && Context->IsCurrent())
if (!Context->IsCurrent())
{
SetError("OpenGL error: %d", error);
return true;
SetError("Unexpected current OpenGL context");
}
GLenum error = glGetError();
if (error == GL_NO_ERROR)
return true;
SetError("OpenGL error: %d", error);
return false;
}
@ -587,16 +595,18 @@ void RenderDevice::SetError(const char* fmt, ...)
{
va_list va;
va_start(va, fmt);
mLastError[sizeof(mLastError) - 1] = 0;
_vsnprintf(mLastError, sizeof(mLastError)-1, fmt, va);
mSetErrorBuffer[0] = 0;
mSetErrorBuffer[sizeof(mSetErrorBuffer) - 1] = 0;
_vsnprintf(mSetErrorBuffer, sizeof(mSetErrorBuffer)-1, fmt, va);
va_end(va);
mLastError = mSetErrorBuffer;
}
const char* RenderDevice::GetError()
{
memcpy(mReturnError, mLastError, sizeof(mReturnError));
mLastError[0] = 0;
return mReturnError;
mReturnError.swap(mLastError);
mLastError.clear();
return mReturnError.c_str();
}
Shader* RenderDevice::GetActiveShader()
@ -630,44 +640,43 @@ void RenderDevice::SetUniform(UniformName name, const void* values, int count)
}
}
void RenderDevice::ApplyChanges()
bool RenderDevice::ApplyChanges()
{
if (mShaderChanged)
ApplyShader();
if (mVertexBufferChanged)
ApplyVertexBuffer();
if (mIndexBufferChanged)
ApplyIndexBuffer();
if (mUniformsChanged)
ApplyUniforms();
if (mTexturesChanged)
ApplyTextures();
if (mRasterizerStateChanged)
ApplyRasterizerState();
if (mBlendStateChanged)
ApplyBlendState();
if (mDepthStateChanged)
ApplyDepthState();
if (mShaderChanged && !ApplyShader()) return false;
if (mVertexBufferChanged && !ApplyVertexBuffer()) return false;
if (mIndexBufferChanged && !ApplyIndexBuffer()) return false;
if (mUniformsChanged && !ApplyUniforms()) return false;
if (mTexturesChanged && !ApplyTextures()) return false;
if (mRasterizerStateChanged && !ApplyRasterizerState()) return false;
if (mBlendStateChanged && !ApplyBlendState()) return false;
if (mDepthStateChanged && !ApplyDepthState()) return false;
mNeedApply = false;
return true;
}
void RenderDevice::ApplyShader()
bool RenderDevice::ApplyViewport()
{
glViewport(0, 0, mViewportWidth, mViewportHeight);
return CheckGLError();
}
bool RenderDevice::ApplyShader()
{
Shader* curShader = GetActiveShader();
if (!curShader->CheckCompile(this))
{
SetError("Failed to bind shader:\r\n%s", curShader->GetCompileError().c_str());
return;
return false;
}
curShader->Bind();
mShaderChanged = false;
CheckGLError();
return CheckGLError();
}
void RenderDevice::ApplyRasterizerState()
bool RenderDevice::ApplyRasterizerState()
{
if (mCullMode == Cull::None)
{
@ -684,10 +693,10 @@ void RenderDevice::ApplyRasterizerState()
mRasterizerStateChanged = false;
CheckGLError();
return CheckGLError();
}
void RenderDevice::ApplyBlendState()
bool RenderDevice::ApplyBlendState()
{
if (mAlphaBlend)
{
@ -705,10 +714,10 @@ void RenderDevice::ApplyBlendState()
mBlendStateChanged = false;
CheckGLError();
return CheckGLError();
}
void RenderDevice::ApplyDepthState()
bool RenderDevice::ApplyDepthState()
{
if (mDepthTest)
{
@ -723,10 +732,10 @@ void RenderDevice::ApplyDepthState()
mDepthStateChanged = false;
CheckGLError();
return CheckGLError();
}
void RenderDevice::ApplyIndexBuffer()
bool RenderDevice::ApplyIndexBuffer()
{
if (mIndexBuffer)
{
@ -739,17 +748,17 @@ void RenderDevice::ApplyIndexBuffer()
mIndexBufferChanged = false;
CheckGLError();
return CheckGLError();
}
void RenderDevice::ApplyVertexBuffer()
bool RenderDevice::ApplyVertexBuffer()
{
if (mVertexBuffer != -1)
glBindVertexArray(mSharedVertexBuffers[mVertexBuffer]->GetVAO());
mVertexBufferChanged = false;
CheckGLError();
return CheckGLError();
}
void RenderDevice::DeclareUniform(UniformName name, const char* glslname, UniformType type)
@ -762,7 +771,7 @@ void RenderDevice::DeclareUniform(UniformName name, const char* glslname, Unifor
mUniformData.resize(mUniformData.size() + (type == UniformType::Matrix ? 16 : 4));
}
void RenderDevice::ApplyUniforms()
bool RenderDevice::ApplyUniforms()
{
Shader* shader = GetActiveShader();
auto& locations = shader->UniformLocations;
@ -789,10 +798,10 @@ void RenderDevice::ApplyUniforms()
mUniformsChanged = false;
CheckGLError();
return CheckGLError();
}
void RenderDevice::ApplyTextures()
bool RenderDevice::ApplyTextures()
{
glActiveTexture(GL_TEXTURE0);
if (mTextureUnit.Tex)
@ -827,7 +836,7 @@ void RenderDevice::ApplyTextures()
mTexturesChanged = false;
CheckGLError();
return CheckGLError();
}
/////////////////////////////////////////////////////////////////////////////
@ -944,69 +953,69 @@ void RenderDevice_SetSamplerState(RenderDevice* device, TextureAddress address)
device->SetSamplerState(address);
}
void RenderDevice_Draw(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount)
bool RenderDevice_Draw(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount)
{
device->Draw(type, startIndex, primitiveCount);
return device->Draw(type, startIndex, primitiveCount);
}
void RenderDevice_DrawIndexed(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount)
bool RenderDevice_DrawIndexed(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount)
{
device->DrawIndexed(type, startIndex, primitiveCount);
return device->DrawIndexed(type, startIndex, primitiveCount);
}
void RenderDevice_DrawData(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount, const void* data)
bool RenderDevice_DrawData(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount, const void* data)
{
device->DrawData(type, startIndex, primitiveCount, data);
return device->DrawData(type, startIndex, primitiveCount, data);
}
void RenderDevice_StartRendering(RenderDevice* device, bool clear, int backcolor, Texture* target, bool usedepthbuffer)
bool RenderDevice_StartRendering(RenderDevice* device, bool clear, int backcolor, Texture* target, bool usedepthbuffer)
{
device->StartRendering(clear, backcolor, target, usedepthbuffer);
return device->StartRendering(clear, backcolor, target, usedepthbuffer);
}
void RenderDevice_FinishRendering(RenderDevice* device)
bool RenderDevice_FinishRendering(RenderDevice* device)
{
device->FinishRendering();
return device->FinishRendering();
}
void RenderDevice_Present(RenderDevice* device)
bool RenderDevice_Present(RenderDevice* device)
{
device->Present();
return device->Present();
}
void RenderDevice_ClearTexture(RenderDevice* device, int backcolor, Texture* texture)
bool RenderDevice_ClearTexture(RenderDevice* device, int backcolor, Texture* texture)
{
device->ClearTexture(backcolor, texture);
return device->ClearTexture(backcolor, texture);
}
void RenderDevice_CopyTexture(RenderDevice* device, Texture* dst, CubeMapFace face)
bool RenderDevice_CopyTexture(RenderDevice* device, Texture* dst, CubeMapFace face)
{
device->CopyTexture(dst, face);
return device->CopyTexture(dst, face);
}
void RenderDevice_SetVertexBufferData(RenderDevice* device, VertexBuffer* buffer, void* data, int64_t size, VertexFormat format)
bool RenderDevice_SetVertexBufferData(RenderDevice* device, VertexBuffer* buffer, void* data, int64_t size, VertexFormat format)
{
device->SetVertexBufferData(buffer, data, size, format);
return device->SetVertexBufferData(buffer, data, size, format);
}
void RenderDevice_SetVertexBufferSubdata(RenderDevice* device, VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size)
bool RenderDevice_SetVertexBufferSubdata(RenderDevice* device, VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size)
{
device->SetVertexBufferSubdata(buffer, destOffset, data, size);
return device->SetVertexBufferSubdata(buffer, destOffset, data, size);
}
void RenderDevice_SetIndexBufferData(RenderDevice* device, IndexBuffer* buffer, void* data, int64_t size)
bool RenderDevice_SetIndexBufferData(RenderDevice* device, IndexBuffer* buffer, void* data, int64_t size)
{
device->SetIndexBufferData(buffer, data, size);
return device->SetIndexBufferData(buffer, data, size);
}
void RenderDevice_SetPixels(RenderDevice* device, Texture* texture, const void* data)
bool RenderDevice_SetPixels(RenderDevice* device, Texture* texture, const void* data)
{
device->SetPixels(texture, data);
return device->SetPixels(texture, data);
}
void RenderDevice_SetCubePixels(RenderDevice* device, Texture* texture, CubeMapFace face, const void* data)
bool RenderDevice_SetCubePixels(RenderDevice* device, Texture* texture, CubeMapFace face, const void* data)
{
device->SetCubePixels(texture, face, data);
return device->SetCubePixels(texture, face, data);
}
void* RenderDevice_MapPBO(RenderDevice* device, Texture* texture)
@ -1014,9 +1023,9 @@ void* RenderDevice_MapPBO(RenderDevice* device, Texture* texture)
return device->MapPBO(texture);
}
void RenderDevice_UnmapPBO(RenderDevice* device, Texture* texture)
bool RenderDevice_UnmapPBO(RenderDevice* device, Texture* texture)
{
device->UnmapPBO(texture);
return device->UnmapPBO(texture);
}
#ifdef NO_SSE

View file

@ -99,36 +99,36 @@ public:
void SetTexture(Texture* texture);
void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy);
void SetSamplerState(TextureAddress address);
void Draw(PrimitiveType type, int startIndex, int primitiveCount);
void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount);
void DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data);
void StartRendering(bool clear, int backcolor, Texture* target, bool usedepthbuffer);
void FinishRendering();
void Present();
void ClearTexture(int backcolor, Texture* texture);
void CopyTexture(Texture* dst, CubeMapFace face);
bool Draw(PrimitiveType type, int startIndex, int primitiveCount);
bool DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount);
bool DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data);
bool StartRendering(bool clear, int backcolor, Texture* target, bool usedepthbuffer);
bool FinishRendering();
bool Present();
bool ClearTexture(int backcolor, Texture* texture);
bool CopyTexture(Texture* dst, CubeMapFace face);
void SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t size, VertexFormat format);
void SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size);
void SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t size);
bool SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t size, VertexFormat format);
bool SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size);
bool SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t size);
void SetPixels(Texture* texture, const void* data);
void SetCubePixels(Texture* texture, CubeMapFace face, const void* data);
bool SetPixels(Texture* texture, const void* data);
bool SetCubePixels(Texture* texture, CubeMapFace face, const void* data);
void* MapPBO(Texture* texture);
void UnmapPBO(Texture* texture);
bool UnmapPBO(Texture* texture);
void InvalidateTexture(Texture* texture);
bool InvalidateTexture(Texture* texture);
void ApplyViewport();
void ApplyChanges();
void ApplyVertexBuffer();
void ApplyIndexBuffer();
void ApplyShader();
void ApplyUniforms();
void ApplyTextures();
void ApplyRasterizerState();
void ApplyBlendState();
void ApplyDepthState();
bool ApplyViewport();
bool ApplyChanges();
bool ApplyVertexBuffer();
bool ApplyIndexBuffer();
bool ApplyShader();
bool ApplyUniforms();
bool ApplyTextures();
bool ApplyRasterizerState();
bool ApplyBlendState();
bool ApplyDepthState();
bool CheckGLError();
void SetError(const char* fmt, ...);
@ -225,8 +225,9 @@ public:
bool mContextIsCurrent = false;
char mLastError[4096];
char mReturnError[4096];
std::string mLastError;
std::string mReturnError;
char mSetErrorBuffer[4096];
int mViewportWidth = 0;
int mViewportHeight = 0;