X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ecere%2Fsrc%2Fgfx%2FDisplay.ec;h=217a181c4e66190a2d951d4918274ce18c308110;hb=c4fa1ba7248b66ba03b51fc1487865a98073e9fd;hp=62c6e94f5bd9b379020a0ca07508ab42a34ae413;hpb=f7225a97e4d484d949f46d1181cbaac0fc92f0d2;p=sdk diff --git a/ecere/src/gfx/Display.ec b/ecere/src/gfx/Display.ec index 62c6e94..217a181 100644 --- a/ecere/src/gfx/Display.ec +++ b/ecere/src/gfx/Display.ec @@ -31,6 +31,42 @@ import "Quaternion" import "Vector3D" #endif +#if (!defined(ECERE_VANILLA) && !defined(ECERE_ONEDRIVER)) +import "OpenGLDisplayDriver" + +#define near _near +#define far _far +#include "gl123es.h" +#undef near +#undef far +#endif + +public class GLCapabilities : uint +{ +public: + // Expect reloading graphics + bool compatible :1; + bool vertexBuffer :1; + bool quads :1; + bool intAndDouble :1; + bool legacyFormats :1; + bool nonPow2Textures :1; + bool vertexPointer :1; + + // Should be able to toggle without reloading + bool legacy :1; + bool shaders :1; + bool fixedFunction :1; + bool immediate :1; + bool frameBuffer :1; + bool pointSize :1; + bool vao :1; + bool select :1; + // bool mapBuffer :1; + + bool debug :1; +}; + public enum RenderState { fillMode = 1, depthTest, depthWrite, fogDensity, fogColor, blend, ambient, alphaWrite, antiAlias, vSync }; public union RenderStateFloat { float f; uint ui; }; @@ -48,7 +84,9 @@ public class FontFlags __attribute__((unused)) static void DummyFunction() { +#if !defined(__EMSCRIPTEN__) Mutex { }; +#endif } public class DisplayDriver @@ -124,10 +162,10 @@ public: virtual bool ::ConvertBitmap(DisplaySystem, Bitmap, PixelFormat, ColorAlpha *); // Converts an LFB bitmap into an offscreen bitmap for this device - virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool); + virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool mipMaps, int cubeMapFace); // Font loading - virtual Font ::LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags); + virtual Font ::LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade); virtual void ::UnloadFont(DisplaySystem, Font); // 2D Drawing @@ -148,9 +186,9 @@ public: virtual void ::FilterDI(Display, Surface, Bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh); virtual void ::TextFont(Display, Surface, Font); virtual void ::TextOpacity(Display, Surface, bool); - virtual void ::WriteText(Display, Surface, int x, int y, const String text, int len); - virtual void ::TextExtent(Display, Surface, const String text, int len, int * tw, int * th); - virtual void ::FontExtent(DisplaySystem, Font, const String text, int len, int * tw, int * th); + virtual void ::WriteText(Display, Surface, int x, int y, const String text, int len, int prevGlyph, int * rPrevGlyph); + virtual void ::TextExtent(Display, Surface, const String text, int len, int * tw, int * th, int prevGlyph, int * rPrevGlyph, int * overHang); + virtual void ::FontExtent(DisplaySystem, Font, const String text, int len, int * tw, int * th, int prevGlyph, int * rPrevGlyph, int * overHang); virtual void ::DrawingChar(Display, Surface, char ch); virtual void ::NextPage(Display); #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D) @@ -179,27 +217,6 @@ public: public enum Alignment { left, right, center }; public enum ClearType { colorBuffer, depthBuffer, colorAndDepth }; -subclass(DisplayDriver) GetDisplayDriver(const char * driverName) -{ - if(driverName) - { - OldLink link; - for(link = class(DisplayDriver).derivatives.first; link; link = link.next) - { - subclass(DisplayDriver) displayDriver = link.data; - if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName)) - return displayDriver; - } - } - return null; -} - -DisplaySystem GetDisplaySystem(const char * driverName) -{ - subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName); - return displayDriver ? displayDriver.displaySystem : null; -} - define textCellW = 8; define textCellH = 16; @@ -240,7 +257,7 @@ public struct Light float multiplier; }; -define NumberOfLights = 8; +public define NumberOfLights = 8; // Painter's algorithm @@ -438,7 +455,7 @@ public: Surface GetSurface(int x, int y, Box clip) { Surface result = null; - Surface surface { }; + Surface surface { _refCount = 1 }; if(surface) { Box box { -x, -y, -x + width - 1, -y + height - 1 }; @@ -506,6 +523,13 @@ public: void FontExtent(Font font, const char * text, int len, int * width, int * height) { + int overHang = 0; + FontExtent2(font, text, len, width, height, 0, null, &overHang); + if(width) *width += overHang; + } + + void FontExtent2(Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * overHang) + { // Fix for OnLoadGraphics time alpha blended window text extent on GDI #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE) if(this && alphaBlend && pixelFormat == pixelFormat888 && @@ -515,14 +539,14 @@ public: if(s) { s.font = font; - s.TextExtent(text, len, width, height); + s.TextExtent2(text, len, width, height, prevGlyph, rPrevGlyph, overHang); delete s; } } else #endif // TODO: Should really pass display here... - DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height); + DisplaySystem::FontExtent2(this ? displaySystem : null, font, text, len, width, height, prevGlyph, rPrevGlyph, overHang); } void SetPalette(ColorAlpha * palette, bool colorMatch) @@ -549,7 +573,9 @@ public: result = displaySystem && displaySystem.Lock(); if(result && render) { +#if !defined(__EMSCRIPTEN__) mutex.Wait(); +#endif if(!current) result = displaySystem.driver.Lock(this); @@ -575,7 +601,9 @@ public: */ if(!current && displaySystem) displaySystem.driver.Unlock(this); +#if !defined(__EMSCRIPTEN__) mutex.Release(); +#endif } if(displaySystem) displaySystem.Unlock(); @@ -689,6 +717,10 @@ public: // --- Lights --- void SetLight(int id, Light light) { + if(!display3D) + { + display3D = Display3D { }; + } displaySystem.driver.SetLight(this, id, light); } @@ -914,6 +946,136 @@ public: if(!display3D.selection && displaySystem.driver.PushMatrix) displaySystem.driver.PushMatrix(this); +#if ENABLE_GL_FFP + if(object.mesh.tangents && object.mesh.normals && object.flags.computeLightVectors) + { + Mesh mesh = object.mesh; + if(!glCaps_shaders) + { + int count = mesh.nVertices; + Vector3Df * normals = mesh.normals; + Vector3Df * vertices = mesh.vertices; + ColorRGB * lightVectors; + Vector3Df * tangents = mesh.tangents; + int i; + float * l = display3D.light0Pos; + Vector3Df light { l[0], l[1], l[2] }; + Matrix o = object.matrix; + Matrix t, inv = camera.viewMatrix; + Vector3D ot { }; + Vector3D cPos = camera.cPosition; + Vector3D pos; + bool positional = l[3] ? true : false; + + inv.Scale(1.0/nearPlane, -1.0/nearPlane,-1.0/nearPlane); + + pos.MultMatrix(cPos, camera.viewMatrix); + + ot.x = o.m[3][0] + pos.x; + ot.y = o.m[3][1] + pos.y; + ot.z = o.m[3][2] + pos.z; + o.m[3][0] = 0; + o.m[3][1] = 0; + o.m[3][2] = 0; + t.Multiply(o, inv); + inv = t; + t.Transpose(inv); + inv.Inverse(t); + + mesh.Allocate({ lightVectors = true }, mesh.nVertices, displaySystem); + mesh.Lock({ lightVectors = true }); + lightVectors = mesh.lightVectors; + for(i = 0; i < count; i++) + { + Vector3Df tangent1 = tangents[i*2 + 0]; + Vector3Df tangent2 = tangents[i*2 + 1]; + Vector3Df normal = normals[i]; + Vector3Df tTangent1, tTangent2, tNormal; + + tTangent1.MultMatrix(tangent1, inv); + tTangent2.MultMatrix(tangent2, inv); + tNormal .MultMatrix(normal, inv); + + tTangent1.Normalize(tTangent1); + tTangent2.Normalize(tTangent2); + tNormal .Normalize(tNormal); + + { + Matrix tbn + { { + tTangent1.x, tTangent2.x, tNormal.x, 0, + tTangent1.y, tTangent2.y, tNormal.y, 0, + tTangent1.z, tTangent2.z, tNormal.z, 1 + } }; + Vector3Df n; + if(positional) + { + Vector3Df tPos = vertices[i]; + tPos.x += ot.x, tPos.y += ot.y, tPos.z += ot.z; + + // Subtract vertex from light for positional lights + light.x = l[0] - tPos.x; + light.y = l[1] + tPos.y; + light.z = l[2] - tPos.z; + } + n.MultMatrix(light, tbn); + if(positional) + n.Normalize(n); + lightVectors[i] = { n.x / 2 + 0.5f, n.y / 2 + 0.5f, n.z / 2 + 0.5f }; + } + } + mesh.Unlock({ lightVectors = true }); + + // Create normalization cube map + /* + if(!mesh.normMap) + mesh.normMap = { }; + { + int w = 256, h = 256, d = 256; + Vector3Df min = mesh.min, max = mesh.max; + Vector3Df delta + { + (max.x - min.x) / w, + (max.y - min.y) / h, + (max.z - min.z) / d + }; + int i; + for(i = 0; i < 6; i++) + { + Bitmap face = i > 0 ? { } : mesh.normMap; + int x, y; + ColorAlpha * p; + face.Free(); + face.Allocate(null, w, h, 0, pixelFormat888, false); + face.driverData = mesh.normMap.driverData; + p = (ColorAlpha *)face.picture; + for(y = 0; y < h; y++) + { + for(x = 0; x < w; x++, p++) + { + Vector3Df v { min.x + x * delta.x, min.y + y * delta.y, min.z }; + v.Normalize(v); + *p = ColorAlpha { 255, { + (byte)((v.x / 2.0 + 0.5) * 255), + (byte)((v.y / 2.0 + 0.5) * 255), + (byte)((v.z / 2.0 + 0.5) * 255) } }; + } + } + displaySystem.driver.MakeDDBitmap(displaySystem, face, true, (i + 1)); + if(i > 0) + { + face.driverData = 0; + delete face; + } + } + } + */ + } + else + mesh.Free({ lightVectors = true }); + } +#endif + SetTransform(object.matrix, object.flags.viewSpace); if(display3D.selection) { @@ -1119,6 +1281,36 @@ public: property bool useSharedMemory { set { useSharedMemory = value; } get { return useSharedMemory; } }; property void * systemWindow { get { return window; } }; property DisplaySystem displaySystem { get { return displaySystem; } }; +#ifndef ECERE_VANILLA + property GLCapabilities glCapabilities + { + get { return ((OGLDisplay)driverData).capabilities; } + set + { + glCapabilities = value; + if(driverData && displaySystem.driver == class(OpenGLDisplayDriver)) + { + OGLDisplay oglDisplay = driverData; + if(!oglDisplay.originalCapabilities.fixedFunction) + value.shaders = true; + if(!oglDisplay.originalCapabilities.shaders) + value.fixedFunction = true; + // Disable things that don't work with shaders + if(value.shaders) + { + value.fixedFunction = false; + value.legacy = false; + value.immediate = false; + } + oglDisplay.capabilities = oglDisplay.originalCapabilities & value; + + Lock(true); + OpenGLDisplayDriver::initialDisplaySetup(this, true, false); + Unlock(); + } + } + }; +#endif int width, height; void * driverData; @@ -1128,7 +1320,9 @@ private: DisplaySystem displaySystem; void * window; +#if !defined(__EMSCRIPTEN__) Mutex mutex { }; +#endif int current; #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D) @@ -1137,10 +1331,12 @@ private: bool alphaBlend; void * windowDriverData; bool useSharedMemory; + GLCapabilities glCapabilities; + glCapabilities = { true, true, true, true, true, true, true, true }; }; #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D) -private class Display3D +private class Display3D : struct { // 3D Display int nTriangles; @@ -1164,6 +1360,7 @@ private class Display3D Line rayView, rayWorld, rayLocal; Vector3D rayIntersect; + float light0Pos[4]; ~Display3D() { @@ -1909,3 +2106,25 @@ public int BestColorMatch(ColorAlpha * palette, int start, int end, Color rgb) } return best; } + +// had to move this here due to compiler ordering issue for "get property" symbol +subclass(DisplayDriver) GetDisplayDriver(const char * driverName) +{ + if(driverName) + { + OldLink link; + for(link = class(DisplayDriver).derivatives.first; link; link = link.next) + { + subclass(DisplayDriver) displayDriver = link.data; + if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName)) + return displayDriver; + } + } + return null; +} + +DisplaySystem GetDisplaySystem(const char * driverName) +{ + subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName); + return displayDriver ? displayDriver.displaySystem : null; +}