/*
 * Copyright (C) 2020 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#if ENABLE(GPU_PROCESS) && ENABLE(WEBGL)

#include "GPUProcessConnection.h"
#include "GraphicsContextGLIdentifier.h"
#include "IPCSemaphore.h"
#include "MessageReceiver.h"
#include "RemoteGraphicsContextGLMessages.h"
#include "RemoteResourceCacheProxy.h"
#include "RenderingBackendIdentifier.h"
#include "SharedVideoFrame.h"
#include "StreamClientConnection.h"
#include "WebCoreArgumentCoders.h"
#include <WebCore/GCGLSpan.h>
#include <WebCore/GraphicsContextGL.h>
#include <WebCore/NotImplemented.h>
#include <wtf/HashMap.h>
#include <wtf/WeakPtr.h>

namespace WebKit {

class RemoteGraphicsContextGLInitializationState;
#if ENABLE(VIDEO)
class RemoteVideoFrameObjectHeapProxy;
#endif

// Web process side implementation of GraphicsContextGL interface. The implementation
// converts the interface to a sequence of IPC messages and sends the messages to
// RemoteGraphicsContextGL in GPU process.
// The implementation is largely generated by running Tools/Scripts/generate-gpup-webgl.
class RemoteGraphicsContextGLProxy
    : private IPC::Connection::Client
    , public WebCore::GraphicsContextGL {
public:
#if ENABLE(VIDEO)
    static RefPtr<RemoteGraphicsContextGLProxy> create(IPC::Connection&, const WebCore::GraphicsContextGLAttributes&, RemoteRenderingBackendProxy&, Ref<RemoteVideoFrameObjectHeapProxy>&&);
#else
    static RefPtr<RemoteGraphicsContextGLProxy> create(IPC::Connection&, const WebCore::GraphicsContextGLAttributes&, RemoteRenderingBackendProxy&);
#endif
    ~RemoteGraphicsContextGLProxy();

    // IPC::Connection::Client overrides.
    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
    void didClose(IPC::Connection&) final;
    void didReceiveInvalidMessage(IPC::Connection&, IPC::MessageName) final { }

    // WebCore::GraphicsContextGL overrides.
    std::optional<WebCore::GraphicsContextGL::EGLImageAttachResult> createAndBindEGLImage(GCGLenum, WebCore::GraphicsContextGL::EGLImageSource) override;
    GCEGLSync createEGLSync(ExternalEGLSyncEvent) override;
    std::tuple<GCGLenum, GCGLenum> externalImageTextureBindingPoint() final;
    void reshape(int width, int height) final;
    void setContextVisibility(bool) final;
    bool isGLES2Compliant() const final;
    void markContextChanged() final;
    bool supportsExtension(const String&) final;
    void ensureExtensionEnabled(const String&) final;
    bool isExtensionEnabled(const String&) final;
    void paintRenderingResultsToCanvas(WebCore::ImageBuffer&) final;
    void paintCompositedResultsToCanvas(WebCore::ImageBuffer&) final;
#if ENABLE(MEDIA_STREAM) || ENABLE(WEB_CODECS)
    RefPtr<WebCore::VideoFrame> paintCompositedResultsToVideoFrame() final;
#endif
    GCGLErrorCodeSet getErrors() final;
#if ENABLE(VIDEO)
    bool copyTextureFromMedia(WebCore::MediaPlayer&, PlatformGLObject texture, GCGLenum target, GCGLint level, GCGLenum internalFormat, GCGLenum format, GCGLenum type, bool premultiplyAlpha, bool flipY) final;
    bool copyTextureFromVideoFrame(WebCore::VideoFrame&, PlatformGLObject /* texture */, GCGLenum /* target */, GCGLint /* level */, GCGLenum /* internalFormat */, GCGLenum /* format */, GCGLenum /* type */, bool /* premultiplyAlpha */, bool /* flipY */) final;
    RefPtr<WebCore::Image> videoFrameToImage(WebCore::VideoFrame&) final;
#endif

    void simulateEventForTesting(SimulatedEventForTesting) final;
    void readPixels(WebCore::IntRect, GCGLenum format, GCGLenum type, std::span<uint8_t> data, GCGLint alignment, GCGLint rowLength) final;
    void multiDrawArraysANGLE(GCGLenum mode, GCGLSpanTuple<const GCGLint, const GCGLsizei> firstsAndCounts) final;
    void multiDrawArraysInstancedANGLE(GCGLenum mode, GCGLSpanTuple<const GCGLint, const GCGLsizei, const GCGLsizei> firstsCountsAndInstanceCounts) final;
    void multiDrawElementsANGLE(GCGLenum mode, GCGLSpanTuple<const GCGLsizei, const GCGLsizei> countsAndOffsets, GCGLenum type) final;
    void multiDrawElementsInstancedANGLE(GCGLenum mode, GCGLSpanTuple<const GCGLsizei, const GCGLsizei, const GCGLsizei> countsOffsetsAndInstanceCounts, GCGLenum type) final;
    void multiDrawArraysInstancedBaseInstanceANGLE(GCGLenum mode, GCGLSpanTuple<const GCGLint, const GCGLsizei, const GCGLsizei, const GCGLuint> firstsCountsInstanceCountsAndBaseInstances) final;
    void multiDrawElementsInstancedBaseVertexBaseInstanceANGLE(GCGLenum mode, GCGLSpanTuple<const GCGLsizei, const GCGLsizei, const GCGLsizei, const GCGLint, const GCGLuint> countsOffsetsInstanceCountsBaseVerticesAndBaseInstances, GCGLenum type) final;

    // Functions with a generated implementation. This list is used by generate-gpup-webgl script.
    void activeTexture(GCGLenum texture) final;
    void attachShader(PlatformGLObject program, PlatformGLObject shader) final;
    void bindAttribLocation(PlatformGLObject arg0, GCGLuint index, const String& name) final;
    void bindBuffer(GCGLenum target, PlatformGLObject arg1) final;
    void bindFramebuffer(GCGLenum target, PlatformGLObject arg1) final;
    void bindRenderbuffer(GCGLenum target, PlatformGLObject arg1) final;
    void bindTexture(GCGLenum target, PlatformGLObject arg1) final;
    void blendColor(GCGLclampf red, GCGLclampf green, GCGLclampf blue, GCGLclampf alpha) final;
    void blendEquation(GCGLenum mode) final;
    void blendEquationSeparate(GCGLenum modeRGB, GCGLenum modeAlpha) final;
    void blendFunc(GCGLenum sfactor, GCGLenum dfactor) final;
    void blendFuncSeparate(GCGLenum srcRGB, GCGLenum dstRGB, GCGLenum srcAlpha, GCGLenum dstAlpha) final;
    GCGLenum checkFramebufferStatus(GCGLenum target) final;
    void clear(GCGLbitfield mask) final;
    void clearColor(GCGLclampf red, GCGLclampf green, GCGLclampf blue, GCGLclampf alpha) final;
    void clearDepth(GCGLclampf depth) final;
    void clearStencil(GCGLint s) final;
    void colorMask(GCGLboolean red, GCGLboolean green, GCGLboolean blue, GCGLboolean alpha) final;
    void compileShader(PlatformGLObject arg0) final;
    void copyTexImage2D(GCGLenum target, GCGLint level, GCGLenum internalformat, GCGLint x, GCGLint y, GCGLsizei width, GCGLsizei height, GCGLint border) final;
    void copyTexSubImage2D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLint x, GCGLint y, GCGLsizei width, GCGLsizei height) final;
    PlatformGLObject createBuffer() final;
    PlatformGLObject createFramebuffer() final;
    PlatformGLObject createProgram() final;
    PlatformGLObject createRenderbuffer() final;
    PlatformGLObject createShader(GCGLenum arg0) final;
    PlatformGLObject createTexture() final;
    void cullFace(GCGLenum mode) final;
    void deleteBuffer(PlatformGLObject arg0) final;
    void deleteFramebuffer(PlatformGLObject arg0) final;
    void deleteProgram(PlatformGLObject arg0) final;
    void deleteRenderbuffer(PlatformGLObject arg0) final;
    void deleteShader(PlatformGLObject arg0) final;
    void deleteTexture(PlatformGLObject arg0) final;
    void depthFunc(GCGLenum func) final;
    void depthMask(GCGLboolean flag) final;
    void depthRange(GCGLclampf zNear, GCGLclampf zFar) final;
    void destroyEGLImage(GCEGLImage handle) final;
    void detachShader(PlatformGLObject arg0, PlatformGLObject arg1) final;
    void disable(GCGLenum cap) final;
    void disableVertexAttribArray(GCGLuint index) final;
    void drawArrays(GCGLenum mode, GCGLint first, GCGLsizei count) final;
    void drawElements(GCGLenum mode, GCGLsizei count, GCGLenum type, GCGLintptr offset) final;
    void enable(GCGLenum cap) final;
    void enableVertexAttribArray(GCGLuint index) final;
    void finish() final;
    void flush() final;
    void framebufferRenderbuffer(GCGLenum target, GCGLenum attachment, GCGLenum renderbuffertarget, PlatformGLObject arg3) final;
    void framebufferTexture2D(GCGLenum target, GCGLenum attachment, GCGLenum textarget, PlatformGLObject arg3, GCGLint level) final;
    void frontFace(GCGLenum mode) final;
    void generateMipmap(GCGLenum target) final;
    bool getActiveAttrib(PlatformGLObject program, GCGLuint index, struct WebCore::GraphicsContextGLActiveInfo& arg2) final;
    bool getActiveUniform(PlatformGLObject program, GCGLuint index, struct WebCore::GraphicsContextGLActiveInfo& arg2) final;
    GCGLint getAttribLocation(PlatformGLObject arg0, const String& name) final;
    GCGLint getBufferParameteri(GCGLenum target, GCGLenum pname) final;
    String getString(GCGLenum name) final;
    void getFloatv(GCGLenum pname, std::span<GCGLfloat> value) final;
    void getIntegerv(GCGLenum pname, std::span<GCGLint> value) final;
    void getIntegeri_v(GCGLenum pname, GCGLuint index, std::span<GCGLint, 4> value) final; // NOLINT
    GCGLint64 getInteger64(GCGLenum pname) final;
    GCGLint64 getInteger64i(GCGLenum pname, GCGLuint index) final;
    GCGLint getProgrami(PlatformGLObject program, GCGLenum pname) final;
    void getBooleanv(GCGLenum pname, std::span<GCGLboolean> value) final;
    GCGLint getFramebufferAttachmentParameteri(GCGLenum target, GCGLenum attachment, GCGLenum pname) final;
    String getProgramInfoLog(PlatformGLObject arg0) final;
    GCGLint getRenderbufferParameteri(GCGLenum target, GCGLenum pname) final;
    GCGLint getShaderi(PlatformGLObject arg0, GCGLenum pname) final;
    String getShaderInfoLog(PlatformGLObject arg0) final;
    void getShaderPrecisionFormat(GCGLenum shaderType, GCGLenum precisionType, std::span<GCGLint, 2> range, GCGLint* precision) final;
    String getShaderSource(PlatformGLObject arg0) final;
    GCGLfloat getTexParameterf(GCGLenum target, GCGLenum pname) final;
    GCGLint getTexParameteri(GCGLenum target, GCGLenum pname) final;
    void getUniformfv(PlatformGLObject program, GCGLint location, std::span<GCGLfloat> value) final;
    void getUniformiv(PlatformGLObject program, GCGLint location, std::span<GCGLint> value) final;
    void getUniformuiv(PlatformGLObject program, GCGLint location, std::span<GCGLuint> value) final;
    GCGLint getUniformLocation(PlatformGLObject arg0, const String& name) final;
    GCGLsizeiptr getVertexAttribOffset(GCGLuint index, GCGLenum pname) final;
    void hint(GCGLenum target, GCGLenum mode) final;
    GCGLboolean isBuffer(PlatformGLObject arg0) final;
    GCGLboolean isEnabled(GCGLenum cap) final;
    GCGLboolean isFramebuffer(PlatformGLObject arg0) final;
    GCGLboolean isProgram(PlatformGLObject arg0) final;
    GCGLboolean isRenderbuffer(PlatformGLObject arg0) final;
    GCGLboolean isShader(PlatformGLObject arg0) final;
    GCGLboolean isTexture(PlatformGLObject arg0) final;
    void lineWidth(GCGLfloat arg0) final;
    void linkProgram(PlatformGLObject arg0) final;
    void pixelStorei(GCGLenum pname, GCGLint param) final;
    void polygonOffset(GCGLfloat factor, GCGLfloat units) final;
    void renderbufferStorage(GCGLenum target, GCGLenum internalformat, GCGLsizei width, GCGLsizei height) final;
    void sampleCoverage(GCGLclampf value, GCGLboolean invert) final;
    void scissor(GCGLint x, GCGLint y, GCGLsizei width, GCGLsizei height) final;
    void shaderSource(PlatformGLObject arg0, const String&) final;
    void stencilFunc(GCGLenum func, GCGLint ref, GCGLuint mask) final;
    void stencilFuncSeparate(GCGLenum face, GCGLenum func, GCGLint ref, GCGLuint mask) final;
    void stencilMask(GCGLuint mask) final;
    void stencilMaskSeparate(GCGLenum face, GCGLuint mask) final;
    void stencilOp(GCGLenum fail, GCGLenum zfail, GCGLenum zpass) final;
    void stencilOpSeparate(GCGLenum face, GCGLenum fail, GCGLenum zfail, GCGLenum zpass) final;
    void texParameterf(GCGLenum target, GCGLenum pname, GCGLfloat param) final;
    void texParameteri(GCGLenum target, GCGLenum pname, GCGLint param) final;
    void uniform1f(GCGLint location, GCGLfloat x) final;
    void uniform1fv(GCGLint location, std::span<const GCGLfloat> v) final;
    void uniform1i(GCGLint location, GCGLint x) final;
    void uniform1iv(GCGLint location, std::span<const GCGLint> v) final;
    void uniform2f(GCGLint location, GCGLfloat x, GCGLfloat y) final;
    void uniform2fv(GCGLint location, std::span<const GCGLfloat> v) final;
    void uniform2i(GCGLint location, GCGLint x, GCGLint y) final;
    void uniform2iv(GCGLint location, std::span<const GCGLint> v) final;
    void uniform3f(GCGLint location, GCGLfloat x, GCGLfloat y, GCGLfloat z) final;
    void uniform3fv(GCGLint location, std::span<const GCGLfloat> v) final;
    void uniform3i(GCGLint location, GCGLint x, GCGLint y, GCGLint z) final;
    void uniform3iv(GCGLint location, std::span<const GCGLint> v) final;
    void uniform4f(GCGLint location, GCGLfloat x, GCGLfloat y, GCGLfloat z, GCGLfloat w) final;
    void uniform4fv(GCGLint location, std::span<const GCGLfloat> v) final;
    void uniform4i(GCGLint location, GCGLint x, GCGLint y, GCGLint z, GCGLint w) final;
    void uniform4iv(GCGLint location, std::span<const GCGLint> v) final;
    void uniformMatrix2fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> value) final;
    void uniformMatrix3fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> value) final;
    void uniformMatrix4fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> value) final;
    void useProgram(PlatformGLObject arg0) final;
    void validateProgram(PlatformGLObject arg0) final;
    void vertexAttrib1f(GCGLuint index, GCGLfloat x) final;
    void vertexAttrib1fv(GCGLuint index, std::span<const GCGLfloat, 1> values) final;
    void vertexAttrib2f(GCGLuint index, GCGLfloat x, GCGLfloat y) final;
    void vertexAttrib2fv(GCGLuint index, std::span<const GCGLfloat, 2> values) final;
    void vertexAttrib3f(GCGLuint index, GCGLfloat x, GCGLfloat y, GCGLfloat z) final;
    void vertexAttrib3fv(GCGLuint index, std::span<const GCGLfloat, 3> values) final;
    void vertexAttrib4f(GCGLuint index, GCGLfloat x, GCGLfloat y, GCGLfloat z, GCGLfloat w) final;
    void vertexAttrib4fv(GCGLuint index, std::span<const GCGLfloat, 4> values) final;
    void vertexAttribPointer(GCGLuint index, GCGLint size, GCGLenum type, GCGLboolean normalized, GCGLsizei stride, GCGLintptr offset) final;
    void viewport(GCGLint x, GCGLint y, GCGLsizei width, GCGLsizei height) final;
    void bufferData(GCGLenum target, GCGLsizeiptr arg1, GCGLenum usage) final;
    void bufferData(GCGLenum target, std::span<const uint8_t> data, GCGLenum usage) final;
    void bufferSubData(GCGLenum target, GCGLintptr offset, std::span<const uint8_t> data) final;
    void readPixelsBufferObject(WebCore::IntRect, GCGLenum format, GCGLenum type, GCGLintptr offset, GCGLint alignment, GCGLint rowLength) final;
    void texImage2D(GCGLenum target, GCGLint level, GCGLenum internalformat, GCGLsizei width, GCGLsizei height, GCGLint border, GCGLenum format, GCGLenum type, std::span<const uint8_t> pixels) final;
    void texImage2D(GCGLenum target, GCGLint level, GCGLenum internalformat, GCGLsizei width, GCGLsizei height, GCGLint border, GCGLenum format, GCGLenum type, GCGLintptr offset) final;
    void texSubImage2D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLsizei width, GCGLsizei height, GCGLenum format, GCGLenum type, std::span<const uint8_t> pixels) final;
    void texSubImage2D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLsizei width, GCGLsizei height, GCGLenum format, GCGLenum type, GCGLintptr offset) final;
    void compressedTexImage2D(GCGLenum target, GCGLint level, GCGLenum internalformat, GCGLsizei width, GCGLsizei height, GCGLint border, GCGLsizei imageSize, std::span<const uint8_t> data) final;
    void compressedTexImage2D(GCGLenum target, GCGLint level, GCGLenum internalformat, GCGLsizei width, GCGLsizei height, GCGLint border, GCGLsizei imageSize, GCGLintptr offset) final;
    void compressedTexSubImage2D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLsizei width, GCGLsizei height, GCGLenum format, GCGLsizei imageSize, std::span<const uint8_t> data) final;
    void compressedTexSubImage2D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLsizei width, GCGLsizei height, GCGLenum format, GCGLsizei imageSize, GCGLintptr offset) final;
    void drawArraysInstanced(GCGLenum mode, GCGLint first, GCGLsizei count, GCGLsizei primcount) final;
    void drawElementsInstanced(GCGLenum mode, GCGLsizei count, GCGLenum type, GCGLintptr offset, GCGLsizei primcount) final;
    void vertexAttribDivisor(GCGLuint index, GCGLuint divisor) final;
    PlatformGLObject createVertexArray() final;
    void deleteVertexArray(PlatformGLObject arg0) final;
    GCGLboolean isVertexArray(PlatformGLObject arg0) final;
    void bindVertexArray(PlatformGLObject arg0) final;
    void copyBufferSubData(GCGLenum readTarget, GCGLenum writeTarget, GCGLintptr readOffset, GCGLintptr writeOffset, GCGLsizeiptr) final;
    void getBufferSubData(GCGLenum target, GCGLintptr offset, std::span<uint8_t> data) final;
    void blitFramebuffer(GCGLint srcX0, GCGLint srcY0, GCGLint srcX1, GCGLint srcY1, GCGLint dstX0, GCGLint dstY0, GCGLint dstX1, GCGLint dstY1, GCGLbitfield mask, GCGLenum filter) final;
    void framebufferTextureLayer(GCGLenum target, GCGLenum attachment, PlatformGLObject texture, GCGLint level, GCGLint layer) final;
    void invalidateFramebuffer(GCGLenum target, std::span<const GCGLenum> attachments) final;
    void invalidateSubFramebuffer(GCGLenum target, std::span<const GCGLenum> attachments, GCGLint x, GCGLint y, GCGLsizei width, GCGLsizei height) final;
    void readBuffer(GCGLenum src) final;
    void renderbufferStorageMultisample(GCGLenum target, GCGLsizei samples, GCGLenum internalformat, GCGLsizei width, GCGLsizei height) final;
    void texStorage2D(GCGLenum target, GCGLsizei levels, GCGLenum internalformat, GCGLsizei width, GCGLsizei height) final;
    void texStorage3D(GCGLenum target, GCGLsizei levels, GCGLenum internalformat, GCGLsizei width, GCGLsizei height, GCGLsizei depth) final;
    void texImage3D(GCGLenum target, GCGLint level, GCGLint internalformat, GCGLsizei width, GCGLsizei height, GCGLsizei depth, GCGLint border, GCGLenum format, GCGLenum type, std::span<const uint8_t> pixels) final;
    void texImage3D(GCGLenum target, GCGLint level, GCGLint internalformat, GCGLsizei width, GCGLsizei height, GCGLsizei depth, GCGLint border, GCGLenum format, GCGLenum type, GCGLintptr offset) final;
    void texSubImage3D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLint zoffset, GCGLsizei width, GCGLsizei height, GCGLsizei depth, GCGLenum format, GCGLenum type, std::span<const uint8_t> pixels) final;
    void texSubImage3D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLint zoffset, GCGLsizei width, GCGLsizei height, GCGLsizei depth, GCGLenum format, GCGLenum type, GCGLintptr offset) final;
    void copyTexSubImage3D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLint zoffset, GCGLint x, GCGLint y, GCGLsizei width, GCGLsizei height) final;
    void compressedTexImage3D(GCGLenum target, GCGLint level, GCGLenum internalformat, GCGLsizei width, GCGLsizei height, GCGLsizei depth, GCGLint border, GCGLsizei imageSize, std::span<const uint8_t> data) final;
    void compressedTexImage3D(GCGLenum target, GCGLint level, GCGLenum internalformat, GCGLsizei width, GCGLsizei height, GCGLsizei depth, GCGLint border, GCGLsizei imageSize, GCGLintptr offset) final;
    void compressedTexSubImage3D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLint zoffset, GCGLsizei width, GCGLsizei height, GCGLsizei depth, GCGLenum format, GCGLsizei imageSize, std::span<const uint8_t> data) final;
    void compressedTexSubImage3D(GCGLenum target, GCGLint level, GCGLint xoffset, GCGLint yoffset, GCGLint zoffset, GCGLsizei width, GCGLsizei height, GCGLsizei depth, GCGLenum format, GCGLsizei imageSize, GCGLintptr offset) final;
    GCGLint getFragDataLocation(PlatformGLObject program, const String& name) final;
    void uniform1ui(GCGLint location, GCGLuint v0) final;
    void uniform2ui(GCGLint location, GCGLuint v0, GCGLuint v1) final;
    void uniform3ui(GCGLint location, GCGLuint v0, GCGLuint v1, GCGLuint v2) final;
    void uniform4ui(GCGLint location, GCGLuint v0, GCGLuint v1, GCGLuint v2, GCGLuint v3) final;
    void uniform1uiv(GCGLint location, std::span<const GCGLuint> data) final;
    void uniform2uiv(GCGLint location, std::span<const GCGLuint> data) final;
    void uniform3uiv(GCGLint location, std::span<const GCGLuint> data) final;
    void uniform4uiv(GCGLint location, std::span<const GCGLuint> data) final;
    void uniformMatrix2x3fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> data) final;
    void uniformMatrix3x2fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> data) final;
    void uniformMatrix2x4fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> data) final;
    void uniformMatrix4x2fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> data) final;
    void uniformMatrix3x4fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> data) final;
    void uniformMatrix4x3fv(GCGLint location, GCGLboolean transpose, std::span<const GCGLfloat> data) final;
    void vertexAttribI4i(GCGLuint index, GCGLint x, GCGLint y, GCGLint z, GCGLint w) final;
    void vertexAttribI4iv(GCGLuint index, std::span<const GCGLint, 4> values) final;
    void vertexAttribI4ui(GCGLuint index, GCGLuint x, GCGLuint y, GCGLuint z, GCGLuint w) final;
    void vertexAttribI4uiv(GCGLuint index, std::span<const GCGLuint, 4> values) final;
    void vertexAttribIPointer(GCGLuint index, GCGLint size, GCGLenum type, GCGLsizei stride, GCGLintptr offset) final;
    void drawRangeElements(GCGLenum mode, GCGLuint start, GCGLuint end, GCGLsizei count, GCGLenum type, GCGLintptr offset) final;
    void drawBuffers(std::span<const GCGLenum> bufs) final;
    void clearBufferiv(GCGLenum buffer, GCGLint drawbuffer, std::span<const GCGLint> values) final;
    void clearBufferuiv(GCGLenum buffer, GCGLint drawbuffer, std::span<const GCGLuint> values) final;
    void clearBufferfv(GCGLenum buffer, GCGLint drawbuffer, std::span<const GCGLfloat> values) final;
    void clearBufferfi(GCGLenum buffer, GCGLint drawbuffer, GCGLfloat depth, GCGLint stencil) final;
    PlatformGLObject createQuery() final;
    void deleteQuery(PlatformGLObject query) final;
    GCGLboolean isQuery(PlatformGLObject query) final;
    void beginQuery(GCGLenum target, PlatformGLObject query) final;
    void endQuery(GCGLenum target) final;
    GCGLint getQuery(GCGLenum target, GCGLenum pname) final;
    GCGLuint getQueryObjectui(PlatformGLObject query, GCGLenum pname) final;
    PlatformGLObject createSampler() final;
    void deleteSampler(PlatformGLObject sampler) final;
    GCGLboolean isSampler(PlatformGLObject sampler) final;
    void bindSampler(GCGLuint unit, PlatformGLObject sampler) final;
    void samplerParameteri(PlatformGLObject sampler, GCGLenum pname, GCGLint param) final;
    void samplerParameterf(PlatformGLObject sampler, GCGLenum pname, GCGLfloat param) final;
    GCGLfloat getSamplerParameterf(PlatformGLObject sampler, GCGLenum pname) final;
    GCGLint getSamplerParameteri(PlatformGLObject sampler, GCGLenum pname) final;
    GCGLsync fenceSync(GCGLenum condition, GCGLbitfield flags) final;
    GCGLboolean isSync(GCGLsync arg0) final;
    void deleteSync(GCGLsync arg0) final;
    GCGLenum clientWaitSync(GCGLsync arg0, GCGLbitfield flags, GCGLuint64 timeout) final;
    void waitSync(GCGLsync arg0, GCGLbitfield flags, GCGLint64 timeout) final;
    GCGLint getSynci(GCGLsync arg0, GCGLenum pname) final;
    PlatformGLObject createTransformFeedback() final;
    void deleteTransformFeedback(PlatformGLObject id) final;
    GCGLboolean isTransformFeedback(PlatformGLObject id) final;
    void bindTransformFeedback(GCGLenum target, PlatformGLObject id) final;
    void beginTransformFeedback(GCGLenum primitiveMode) final;
    void endTransformFeedback() final;
    void transformFeedbackVaryings(PlatformGLObject program, const Vector<String>& varyings, GCGLenum bufferMode) final;
    void getTransformFeedbackVarying(PlatformGLObject program, GCGLuint index, struct WebCore::GraphicsContextGLActiveInfo& arg2) final;
    void pauseTransformFeedback() final;
    void resumeTransformFeedback() final;
    void bindBufferBase(GCGLenum target, GCGLuint index, PlatformGLObject buffer) final;
    void bindBufferRange(GCGLenum target, GCGLuint index, PlatformGLObject buffer, GCGLintptr offset, GCGLsizeiptr) final;
    Vector<GCGLuint> getUniformIndices(PlatformGLObject program, const Vector<String>& uniformNames) final;
    Vector<GCGLint> getActiveUniforms(PlatformGLObject program, const Vector<GCGLuint>& uniformIndices, GCGLenum pname) final;
    GCGLuint getUniformBlockIndex(PlatformGLObject program, const String& uniformBlockName) final;
    String getActiveUniformBlockName(PlatformGLObject program, GCGLuint uniformBlockIndex) final;
    void uniformBlockBinding(PlatformGLObject program, GCGLuint uniformBlockIndex, GCGLuint uniformBlockBinding) final;
    void getActiveUniformBlockiv(GCGLuint program, GCGLuint uniformBlockIndex, GCGLenum pname, std::span<GCGLint> params) final;
    String getTranslatedShaderSourceANGLE(PlatformGLObject arg0) final;
    void drawBuffersEXT(std::span<const GCGLenum> bufs) final;
    PlatformGLObject createQueryEXT() final;
    void deleteQueryEXT(PlatformGLObject query) final;
    GCGLboolean isQueryEXT(PlatformGLObject query) final;
    void beginQueryEXT(GCGLenum target, PlatformGLObject query) final;
    void endQueryEXT(GCGLenum target) final;
    void queryCounterEXT(PlatformGLObject query, GCGLenum target) final;
    GCGLint getQueryiEXT(GCGLenum target, GCGLenum pname) final;
    GCGLint getQueryObjectiEXT(PlatformGLObject query, GCGLenum pname) final;
    GCGLuint64 getQueryObjectui64EXT(PlatformGLObject query, GCGLenum pname) final;
    GCGLint64 getInteger64EXT(GCGLenum pname) final;
    void enableiOES(GCGLenum target, GCGLuint index) final;
    void disableiOES(GCGLenum target, GCGLuint index) final;
    void blendEquationiOES(GCGLuint buf, GCGLenum mode) final;
    void blendEquationSeparateiOES(GCGLuint buf, GCGLenum modeRGB, GCGLenum modeAlpha) final;
    void blendFunciOES(GCGLuint buf, GCGLenum src, GCGLenum dst) final;
    void blendFuncSeparateiOES(GCGLuint buf, GCGLenum srcRGB, GCGLenum dstRGB, GCGLenum srcAlpha, GCGLenum dstAlpha) final;
    void colorMaskiOES(GCGLuint buf, GCGLboolean red, GCGLboolean green, GCGLboolean blue, GCGLboolean alpha) final;
    void drawArraysInstancedBaseInstanceANGLE(GCGLenum mode, GCGLint first, GCGLsizei count, GCGLsizei instanceCount, GCGLuint baseInstance) final;
    void drawElementsInstancedBaseVertexBaseInstanceANGLE(GCGLenum mode, GCGLsizei count, GCGLenum type, GCGLintptr offset, GCGLsizei instanceCount, GCGLint baseVertex, GCGLuint baseInstance) final;
    void provokingVertexANGLE(GCGLenum provokeMode) final;
    void polygonOffsetClampEXT(GCGLfloat factor, GCGLfloat units, GCGLfloat clamp) final;
    void renderbufferStorageMultisampleANGLE(GCGLenum target, GCGLsizei samples, GCGLenum internalformat, GCGLsizei width, GCGLsizei height) final;
    void blitFramebufferANGLE(GCGLint srcX0, GCGLint srcY0, GCGLint srcX1, GCGLint srcY1, GCGLint dstX0, GCGLint dstY0, GCGLint dstX1, GCGLint dstY1, GCGLbitfield mask, GCGLenum filter) final;
    void getInternalformativ(GCGLenum target, GCGLenum internalformat, GCGLenum pname, std::span<GCGLint> params) final;
    void setDrawingBufferColorSpace(const WebCore::DestinationColorSpace&) final;
    RefPtr<WebCore::PixelBuffer> paintRenderingResultsToPixelBuffer() final;
    bool destroyEGLSync(GCEGLSync) final;
    void clientWaitEGLSyncWithFlush(GCEGLSync, uint64_t timeout) final;
    // End of list used by generate-gpup-webgl script.

    static bool handleMessageToRemovedDestination(IPC::Connection&, IPC::Decoder&);

protected:
#if ENABLE(VIDEO)
    RemoteGraphicsContextGLProxy(IPC::Connection&, RefPtr<IPC::StreamClientConnection>, const WebCore::GraphicsContextGLAttributes&, Ref<RemoteVideoFrameObjectHeapProxy>&&);
#else
    RemoteGraphicsContextGLProxy(IPC::Connection&, RefPtr<IPC::StreamClientConnection>, const WebCore::GraphicsContextGLAttributes&);
#endif

    bool isContextLost() const { return !m_connection; }
    void markContextLost();

    static inline Seconds defaultSendTimeout = 30_s;
    template<typename T>
    WARN_UNUSED_RETURN IPC::Error send(T&& message)
    {
        return m_streamConnection->send(WTFMove(message), m_graphicsContextGLIdentifier, defaultSendTimeout);
    }
    template<typename T>
    WARN_UNUSED_RETURN IPC::Connection::SendSyncResult<T> sendSync(T&& message)
    {
        return m_streamConnection->sendSync(WTFMove(message), m_graphicsContextGLIdentifier, defaultSendTimeout);
    }

    GraphicsContextGLIdentifier m_graphicsContextGLIdentifier { GraphicsContextGLIdentifier::generate() };
private:
#if ENABLE(VIDEO)
    static Ref<RemoteGraphicsContextGLProxy> platformCreate(IPC::Connection&, Ref<IPC::StreamClientConnection>, const WebCore::GraphicsContextGLAttributes&, Ref<RemoteVideoFrameObjectHeapProxy>&&);
#else 
    static Ref<RemoteGraphicsContextGLProxy> platformCreate(IPC::Connection&, Ref<IPC::StreamClientConnection>, const WebCore::GraphicsContextGLAttributes&);
#endif
    void initializeIPC(IPC::StreamServerConnection::Handle&&, RemoteRenderingBackendProxy&);
    // Messages to be received.
    void wasCreated(IPC::Semaphore&&, IPC::Semaphore&&, std::optional<RemoteGraphicsContextGLInitializationState>&&);
    void wasLost();
    void wasChanged();

    void readPixelsSharedMemory(WebCore::IntRect, GCGLenum format, GCGLenum type, std::span<uint8_t> data);

    void initialize(const RemoteGraphicsContextGLInitializationState&);
    void waitUntilInitialized();
    void disconnectGpuProcessIfNeeded();
    void abandonGpuProcess();

    RefPtr<IPC::Connection> m_connection;
    bool m_didInitialize { false };
    // Guarded by waitUntilInitialized().
    HashSet<String> m_availableExtensions;
    HashSet<String> m_requestableExtensions;

    HashSet<String> m_enabledExtensions;
    RefPtr<IPC::StreamClientConnection> m_streamConnection;
#if PLATFORM(COCOA)
    SharedVideoFrameWriter m_sharedVideoFrameWriter;
#endif
#if ENABLE(VIDEO)
    Ref<RemoteVideoFrameObjectHeapProxy> m_videoFrameObjectHeapProxy;
#endif
    GCGLenum m_externalImageTarget { 0 };
    GCGLenum m_externalImageBindingQuery { 0 };
};

// The GCGL types map to following WebKit IPC types. The list is used by generate-gpup-webgl script.
static_assert(std::is_same_v<GCGLenum, uint32_t>);
static_assert(sizeof(GCGLboolean) == sizeof(bool));
static_assert(std::is_same_v<GCGLbitfield, uint32_t>);
static_assert(std::is_same_v<GCGLbyte, int8_t>);
static_assert(std::is_same_v<GCGLubyte, uint8_t>);
static_assert(std::is_same_v<GCGLshort, int16_t>);
static_assert(std::is_same_v<GCGLushort, uint16_t>);
static_assert(std::is_same_v<GCGLint, int32_t>);
static_assert(std::is_same_v<GCGLsizei, int32_t>);
static_assert(std::is_same_v<GCGLuint, uint32_t>);
static_assert(std::is_same_v<GCGLfloat, float>);
static_assert(std::is_same_v<GCGLhalffloat, uint16_t>);
static_assert(std::is_same_v<GCGLclampf, float>);
static_assert(std::is_same_v<GCGLvoid, void>);
static_assert(std::is_same_v<PlatformGLObject, uint32_t>);
static_assert(sizeof(GCGLchar) == sizeof(uint8_t));
static_assert(sizeof(GCGLint64) == sizeof(int64_t));
static_assert(sizeof(GCGLuint64) == sizeof(uint64_t));
// GCGLsync and GCGL*ptr types are pointers. On some platforms, they are 32-bit.
// Currently we hard-code it by using <=, and assume that we do not transfer arrays of the types.
static_assert(sizeof(GCGLintptr) <= sizeof(uint64_t));
static_assert(sizeof(GCGLsizeiptr) <= sizeof(uint64_t));
static_assert(sizeof(GCGLvoidptr) <= sizeof(uint64_t));
static_assert(sizeof(GCGLsync) <= sizeof(uint64_t) && sizeof(GCGLsync) == sizeof(intptr_t));
static_assert(sizeof(GCEGLImage) <= sizeof(uint64_t) && sizeof(GCEGLImage) == sizeof(intptr_t));
static_assert(sizeof(GCEGLSync) <= sizeof(uint64_t) && sizeof(GCEGLSync) == sizeof(intptr_t));
// End of list used by generate-gpup-webgl script.

} // namespace WebKit

#endif
