فهرست منبع

LibGL+LibSoftGPU: Support generation of multiple texture coordinates

Stephan Unverwerth 3 سال پیش
والد
کامیت
12f63df329

+ 70 - 52
Userland/Libraries/LibGL/SoftwareGLContext.cpp

@@ -83,6 +83,21 @@ SoftwareGLContext::SoftwareGLContext(Gfx::Bitmap& frontbuffer)
     for (auto& tex_coord : m_current_vertex_tex_coord)
         tex_coord = { 0.0f, 0.0f, 0.0f, 1.0f };
 
+    // Initialize the texture coordinate generation coefficients
+    // Indices 0,1,2,3 refer to the S,T,R and Q coordinate of the respective texture
+    // coordinate generation config.
+    m_texture_coordinate_generation.resize(m_device_info.num_texture_units);
+    for (auto& texture_coordinate_generation : m_texture_coordinate_generation) {
+        texture_coordinate_generation[0].object_plane_coefficients = { 1.0f, 0.0f, 0.0f, 0.0f };
+        texture_coordinate_generation[0].eye_plane_coefficients = { 1.0f, 0.0f, 0.0f, 0.0f };
+        texture_coordinate_generation[1].object_plane_coefficients = { 0.0f, 1.0f, 0.0f, 0.0f };
+        texture_coordinate_generation[1].eye_plane_coefficients = { 0.0f, 1.0f, 0.0f, 0.0f };
+        texture_coordinate_generation[2].object_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f };
+        texture_coordinate_generation[2].eye_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f };
+        texture_coordinate_generation[3].object_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f };
+        texture_coordinate_generation[3].eye_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f };
+    }
+
     build_extension_string();
 }
 
@@ -191,7 +206,7 @@ Optional<ContextParameter> SoftwareGLContext::get_context_parameter(GLenum name)
     case GL_TEXTURE_GEN_R:
     case GL_TEXTURE_GEN_S:
     case GL_TEXTURE_GEN_T: {
-        auto generation_enabled = texture_coordinate_generation(name).enabled;
+        auto generation_enabled = texture_coordinate_generation(m_active_texture_unit_index, name).enabled;
         return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = generation_enabled } };
     }
     case GL_UNPACK_ALIGNMENT:
@@ -748,7 +763,7 @@ void SoftwareGLContext::gl_enable(GLenum capability)
     case GL_TEXTURE_GEN_R:
     case GL_TEXTURE_GEN_S:
     case GL_TEXTURE_GEN_T:
-        texture_coordinate_generation(capability).enabled = true;
+        texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = true;
         m_texcoord_generation_dirty = true;
         break;
     default:
@@ -850,7 +865,7 @@ void SoftwareGLContext::gl_disable(GLenum capability)
     case GL_TEXTURE_GEN_R:
     case GL_TEXTURE_GEN_S:
     case GL_TEXTURE_GEN_T:
-        texture_coordinate_generation(capability).enabled = false;
+        texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = false;
         m_texcoord_generation_dirty = true;
         break;
     default:
@@ -2888,7 +2903,7 @@ void SoftwareGLContext::gl_tex_gen(GLenum coord, GLenum pname, GLint param)
     RETURN_WITH_ERROR_IF(coord == GL_Q && (param == GL_REFLECTION_MAP || param == GL_NORMAL_MAP), GL_INVALID_ENUM);
 
     GLenum const capability = GL_TEXTURE_GEN_S + (coord - GL_S);
-    texture_coordinate_generation(capability).generation_mode = param;
+    texture_coordinate_generation(m_active_texture_unit_index, capability).generation_mode = param;
     m_texcoord_generation_dirty = true;
 }
 
@@ -2917,11 +2932,11 @@ void SoftwareGLContext::gl_tex_gen_floatv(GLenum coord, GLenum pname, GLfloat co
         RETURN_WITH_ERROR_IF((coord == GL_R || coord == GL_Q) && param == GL_SPHERE_MAP, GL_INVALID_ENUM);
         RETURN_WITH_ERROR_IF(coord == GL_Q && (param == GL_REFLECTION_MAP || param == GL_NORMAL_MAP), GL_INVALID_ENUM);
 
-        texture_coordinate_generation(capability).generation_mode = param;
+        texture_coordinate_generation(m_active_texture_unit_index, capability).generation_mode = param;
         break;
     }
     case GL_OBJECT_PLANE:
-        texture_coordinate_generation(capability).object_plane_coefficients = { params[0], params[1], params[2], params[3] };
+        texture_coordinate_generation(m_active_texture_unit_index, capability).object_plane_coefficients = { params[0], params[1], params[2], params[3] };
         break;
     case GL_EYE_PLANE: {
         auto const& inverse_model_view = m_model_view_matrix.inverse();
@@ -2933,7 +2948,7 @@ void SoftwareGLContext::gl_tex_gen_floatv(GLenum coord, GLenum pname, GLfloat co
         // "The returned values are those maintained in eye coordinates. They are not equal to the values
         //  specified using glTexGen, unless the modelview matrix was identity when glTexGen was called."
 
-        texture_coordinate_generation(capability).eye_plane_coefficients = inverse_model_view * input_coefficients;
+        texture_coordinate_generation(m_active_texture_unit_index, capability).eye_plane_coefficients = inverse_model_view * input_coefficients;
         break;
     }
     default:
@@ -3162,55 +3177,58 @@ void SoftwareGLContext::sync_device_texcoord_config()
 
     auto options = m_rasterizer.options();
 
-    u8 enabled_coordinates = SoftGPU::TexCoordGenerationCoordinate::None;
-    for (GLenum capability = GL_TEXTURE_GEN_S; capability <= GL_TEXTURE_GEN_Q; ++capability) {
-        auto const context_coordinate_config = texture_coordinate_generation(capability);
-        if (!context_coordinate_config.enabled)
-            continue;
+    for (size_t i = 0; i < m_device_info.num_texture_units; ++i) {
 
-        SoftGPU::TexCoordGenerationConfig* texcoord_generation_config;
-        switch (capability) {
-        case GL_TEXTURE_GEN_S:
-            enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::S;
-            texcoord_generation_config = &options.texcoord_generation_config[0];
-            break;
-        case GL_TEXTURE_GEN_T:
-            enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::T;
-            texcoord_generation_config = &options.texcoord_generation_config[1];
-            break;
-        case GL_TEXTURE_GEN_R:
-            enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::R;
-            texcoord_generation_config = &options.texcoord_generation_config[2];
-            break;
-        case GL_TEXTURE_GEN_Q:
-            enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::Q;
-            texcoord_generation_config = &options.texcoord_generation_config[3];
-            break;
-        default:
-            VERIFY_NOT_REACHED();
-        }
+        u8 enabled_coordinates = SoftGPU::TexCoordGenerationCoordinate::None;
+        for (GLenum capability = GL_TEXTURE_GEN_S; capability <= GL_TEXTURE_GEN_Q; ++capability) {
+            auto const context_coordinate_config = texture_coordinate_generation(i, capability);
+            if (!context_coordinate_config.enabled)
+                continue;
 
-        switch (context_coordinate_config.generation_mode) {
-        case GL_OBJECT_LINEAR:
-            texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ObjectLinear;
-            texcoord_generation_config->coefficients = context_coordinate_config.object_plane_coefficients;
-            break;
-        case GL_EYE_LINEAR:
-            texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::EyeLinear;
-            texcoord_generation_config->coefficients = context_coordinate_config.eye_plane_coefficients;
-            break;
-        case GL_SPHERE_MAP:
-            texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::SphereMap;
-            break;
-        case GL_REFLECTION_MAP:
-            texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ReflectionMap;
-            break;
-        case GL_NORMAL_MAP:
-            texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::NormalMap;
-            break;
+            SoftGPU::TexCoordGenerationConfig* texcoord_generation_config;
+            switch (capability) {
+            case GL_TEXTURE_GEN_S:
+                enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::S;
+                texcoord_generation_config = &options.texcoord_generation_config[i][0];
+                break;
+            case GL_TEXTURE_GEN_T:
+                enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::T;
+                texcoord_generation_config = &options.texcoord_generation_config[i][1];
+                break;
+            case GL_TEXTURE_GEN_R:
+                enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::R;
+                texcoord_generation_config = &options.texcoord_generation_config[i][2];
+                break;
+            case GL_TEXTURE_GEN_Q:
+                enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::Q;
+                texcoord_generation_config = &options.texcoord_generation_config[i][3];
+                break;
+            default:
+                VERIFY_NOT_REACHED();
+            }
+
+            switch (context_coordinate_config.generation_mode) {
+            case GL_OBJECT_LINEAR:
+                texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ObjectLinear;
+                texcoord_generation_config->coefficients = context_coordinate_config.object_plane_coefficients;
+                break;
+            case GL_EYE_LINEAR:
+                texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::EyeLinear;
+                texcoord_generation_config->coefficients = context_coordinate_config.eye_plane_coefficients;
+                break;
+            case GL_SPHERE_MAP:
+                texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::SphereMap;
+                break;
+            case GL_REFLECTION_MAP:
+                texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ReflectionMap;
+                break;
+            case GL_NORMAL_MAP:
+                texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::NormalMap;
+                break;
+            }
         }
+        options.texcoord_generation_enabled_coordinates[i] = enabled_coordinates;
     }
-    options.texcoord_generation_enabled_coordinates = enabled_coordinates;
 
     m_rasterizer.set_options(options);
 }

+ 5 - 26
Userland/Libraries/LibGL/SoftwareGLContext.h

@@ -270,36 +270,15 @@ private:
     struct TextureCoordinateGeneration {
         bool enabled { false };
         GLenum generation_mode { GL_EYE_LINEAR };
-        FloatVector4 object_plane_coefficients;
-        FloatVector4 eye_plane_coefficients;
-    };
-    Array<TextureCoordinateGeneration, 4> m_texture_coordinate_generation {
-        // S
-        TextureCoordinateGeneration {
-            .object_plane_coefficients = { 1.0f, 0.0f, 0.0f, 0.0f },
-            .eye_plane_coefficients = { 1.0f, 0.0f, 0.0f, 0.0f },
-        },
-        // T
-        TextureCoordinateGeneration {
-            .object_plane_coefficients = { 0.0f, 1.0f, 0.0f, 0.0f },
-            .eye_plane_coefficients = { 0.0f, 1.0f, 0.0f, 0.0f },
-        },
-        // R
-        TextureCoordinateGeneration {
-            .object_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f },
-            .eye_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f },
-        },
-        // Q
-        TextureCoordinateGeneration {
-            .object_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f },
-            .eye_plane_coefficients = { 0.0f, 0.0f, 0.0f, 0.0f },
-        },
+        FloatVector4 object_plane_coefficients { 0.0f, 0.0f, 0.0f, 0.0f };
+        FloatVector4 eye_plane_coefficients { 0.0f, 0.0f, 0.0f, 0.0f };
     };
+    Vector<Array<TextureCoordinateGeneration, 4>> m_texture_coordinate_generation;
     bool m_texcoord_generation_dirty { true };
 
-    ALWAYS_INLINE TextureCoordinateGeneration& texture_coordinate_generation(GLenum capability)
+    ALWAYS_INLINE TextureCoordinateGeneration& texture_coordinate_generation(size_t texture_unit, GLenum capability)
     {
-        return m_texture_coordinate_generation[capability - GL_TEXTURE_GEN_S];
+        return m_texture_coordinate_generation[texture_unit][capability - GL_TEXTURE_GEN_S];
     }
 
     SoftGPU::Device m_rasterizer;

+ 24 - 13
Userland/Libraries/LibSoftGPU/Device.cpp

@@ -612,16 +612,16 @@ DeviceInfo Device::info() const
 
 static void generate_texture_coordinates(Vertex& vertex, RasterizerOptions const& options)
 {
-    auto generate_coordinate = [&](size_t config_index) -> float {
-        auto mode = options.texcoord_generation_config[config_index].mode;
+    auto generate_coordinate = [&](size_t texcoord_index, size_t config_index) -> float {
+        auto mode = options.texcoord_generation_config[texcoord_index][config_index].mode;
 
         switch (mode) {
         case TexCoordGenerationMode::ObjectLinear: {
-            auto coefficients = options.texcoord_generation_config[config_index].coefficients;
+            auto coefficients = options.texcoord_generation_config[texcoord_index][config_index].coefficients;
             return coefficients.dot(vertex.position);
         }
         case TexCoordGenerationMode::EyeLinear: {
-            auto coefficients = options.texcoord_generation_config[config_index].coefficients;
+            auto coefficients = options.texcoord_generation_config[texcoord_index][config_index].coefficients;
             return coefficients.dot(vertex.eye_coordinates);
         }
         case TexCoordGenerationMode::SphereMap: {
@@ -667,13 +667,16 @@ static void generate_texture_coordinates(Vertex& vertex, RasterizerOptions const
         }
     };
 
-    auto const enabled_coords = options.texcoord_generation_enabled_coordinates;
-    vertex.tex_coords[0] = {
-        ((enabled_coords & TexCoordGenerationCoordinate::S) > 0) ? generate_coordinate(0) : vertex.tex_coords[0].x(),
-        ((enabled_coords & TexCoordGenerationCoordinate::T) > 0) ? generate_coordinate(1) : vertex.tex_coords[0].y(),
-        ((enabled_coords & TexCoordGenerationCoordinate::R) > 0) ? generate_coordinate(2) : vertex.tex_coords[0].z(),
-        ((enabled_coords & TexCoordGenerationCoordinate::Q) > 0) ? generate_coordinate(3) : vertex.tex_coords[0].w(),
-    };
+    for (size_t i = 0; i < vertex.tex_coords.size(); ++i) {
+        auto& tex_coord = vertex.tex_coords[i];
+        auto const enabled_coords = options.texcoord_generation_enabled_coordinates[i];
+        tex_coord = {
+            ((enabled_coords & TexCoordGenerationCoordinate::S) > 0) ? generate_coordinate(i, 0) : tex_coord.x(),
+            ((enabled_coords & TexCoordGenerationCoordinate::T) > 0) ? generate_coordinate(i, 1) : tex_coord.y(),
+            ((enabled_coords & TexCoordGenerationCoordinate::R) > 0) ? generate_coordinate(i, 2) : tex_coord.z(),
+            ((enabled_coords & TexCoordGenerationCoordinate::Q) > 0) ? generate_coordinate(i, 3) : tex_coord.w(),
+        };
+    }
 }
 
 void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const& model_view_transform, FloatMatrix3x3 const& normal_transform,
@@ -952,6 +955,15 @@ void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const&
         }
     }
 
+    // Generate texture coordinates if at least one coordinate is enabled
+    bool texture_coordinate_generation_enabled = false;
+    for (auto const coordinates_enabled : m_options.texcoord_generation_enabled_coordinates) {
+        if (coordinates_enabled != TexCoordGenerationCoordinate::None) {
+            texture_coordinate_generation_enabled = true;
+            break;
+        }
+    }
+
     for (auto& triangle : m_processed_triangles) {
         // Let's calculate the (signed) area of the triangle
         // https://cp-algorithms.com/geometry/oriented-triangle-area.html
@@ -987,8 +999,7 @@ void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const&
             triangle.vertices[2].normal.normalize();
         }
 
-        // Generate texture coordinates if at least one coordinate is enabled
-        if (m_options.texcoord_generation_enabled_coordinates != TexCoordGenerationCoordinate::None) {
+        if (texture_coordinate_generation_enabled) {
             generate_texture_coordinates(triangle.vertices[0], m_options);
             generate_texture_coordinates(triangle.vertices[1], m_options);
             generate_texture_coordinates(triangle.vertices[2], m_options);

+ 2 - 2
Userland/Libraries/LibSoftGPU/Device.h

@@ -70,8 +70,8 @@ struct RasterizerOptions {
     WindingOrder front_face { WindingOrder::CounterClockwise };
     bool cull_back { true };
     bool cull_front { false };
-    u8 texcoord_generation_enabled_coordinates { TexCoordGenerationCoordinate::None };
-    Array<TexCoordGenerationConfig, 4> texcoord_generation_config {};
+    Array<u8, NUM_SAMPLERS> texcoord_generation_enabled_coordinates {};
+    Array<Array<TexCoordGenerationConfig, 4>, NUM_SAMPLERS> texcoord_generation_config {};
     Gfx::IntRect viewport;
     bool lighting_enabled { false };
     bool color_material_enabled { false };