Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  gdkmacosglcontext.c

  Sprache: C
 

/*
 * Copyright © 2020 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 */


#include "config.h"

#include "gdkconfig.h"

#include <OpenGL/CGLIOSurface.h>
#include <QuartzCore/QuartzCore.h>

#import "GdkMacosLayer.h"

#include "gdkmacosbuffer-private.h"
#include "gdkmacosglcontext-private.h"
#include "gdkmacossurface-private.h"

G_GNUC_BEGIN_IGNORE_DEPRECATIONS

G_DEFINE_TYPE (GdkMacosGLContext, gdk_macos_gl_context, GDK_TYPE_GL_CONTEXT)

#define CHECK(error,cgl_error) _CHECK_CGL(error, G_STRLOC, cgl_error)
static inline gboolean
_CHECK_CGL (GError     **error,
            const char  *location,
            CGLError     cgl_error)
{
  if (cgl_error != kCGLNoError)
    {
      g_log ("Core OpenGL",
             G_LOG_LEVEL_CRITICAL,
             "%s: %s",
             location, CGLErrorString (cgl_error));
      g_set_error (error,
                   GDK_GL_ERROR,
                   GDK_GL_ERROR_NOT_AVAILABLE,
                   "%s",
                   CGLErrorString (cgl_error));
      return FALSE;
    }

  return TRUE;
}

/* Apple's OpenGL implementation does not contain the extension to
 * perform log handler callbacks when errors occur. Therefore, to aid in
 * tracking down issues we have a CHECK_GL() macro that can wrap GL
 * calls and check for an error afterwards.
 *
 * To make this easier, we use a statement expression, as this will
 * always be using something GCC-compatible on macOS.
 */

#define CHECK_GL(error,func) _CHECK_GL(error, G_STRLOC, ({ func; glGetError(); }))
static inline gboolean
_CHECK_GL (GError     **error,
           const char  *location,
           GLenum       gl_error)
{
  const char *msg;

  switch (gl_error)
    {
    case GL_INVALID_ENUM:
      msg = "invalid enum";
      break;
    case GL_INVALID_VALUE:
      msg = "invalid value";
      break;
    case GL_INVALID_OPERATION:
      msg = "invalid operation";
      break;
    case GL_INVALID_FRAMEBUFFER_OPERATION:
      msg = "invalid framebuffer operation";
      break;
    case GL_OUT_OF_MEMORY:
      msg = "out of memory";
      break;
    default:
      msg = "unknown error";
      break;
    }

  if (gl_error != GL_NO_ERROR)
    {
      g_log ("OpenGL",
             G_LOG_LEVEL_CRITICAL,
             "%s: %s", location, msg);
      if (error != NULL)
        g_set_error (error,
                     GDK_GL_ERROR,
                     GDK_GL_ERROR_NOT_AVAILABLE,
                     "%s", msg);
      return FALSE;
    }

  return TRUE;
}

static gboolean
check_framebuffer_status (GLenum target)
{
  switch (glCheckFramebufferStatus (target))
    {
    case GL_FRAMEBUFFER_COMPLETE:
      return TRUE;

    case GL_FRAMEBUFFER_UNDEFINED:
      g_critical ("Framebuffer is undefined");
      return FALSE;

    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
      g_critical ("Framebuffer has incomplete attachment");
      return FALSE;

    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
      g_critical ("Framebuffer has missing attachment");
      return FALSE;

    case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
      g_critical ("Framebuffer has incomplete draw buffer");
      return FALSE;

    case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
      g_critical ("Framebuffer has incomplete read buffer");
      return FALSE;

    case GL_FRAMEBUFFER_UNSUPPORTED:
      g_critical ("Framebuffer is unsupported");
      return FALSE;

    case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
      g_critical ("Framebuffer has incomplete multisample");
      return FALSE;

    default:
      g_critical ("Framebuffer has unknown error");
      return FALSE;
    }
}

static const char *
get_renderer_name (GLint id)
{
  static char renderer_name[32];

  switch (id & kCGLRendererIDMatchingMask)
  {
  case kCGLRendererGenericID: return "Generic";
  case kCGLRendererGenericFloatID: return "Generic Float";
  case kCGLRendererAppleSWID: return "Apple Software Renderer";
  case kCGLRendererATIRage128ID: return "ATI Rage 128";
  case kCGLRendererATIRadeonID: return "ATI Radeon";
  case kCGLRendererATIRageProID: return "ATI Rage Pro";
  case kCGLRendererATIRadeon8500ID: return "ATI Radeon 8500";
  case kCGLRendererATIRadeon9700ID: return "ATI Radeon 9700";
  case kCGLRendererATIRadeonX1000ID: return "ATI Radeon X1000";
  case kCGLRendererATIRadeonX2000ID: return "ATI Radeon X2000";
  case kCGLRendererATIRadeonX3000ID: return "ATI Radeon X3000";
  case kCGLRendererATIRadeonX4000ID: return "ATI Radeon X4000";
  case kCGLRendererGeForce2MXID: return "GeForce 2 MX";
  case kCGLRendererGeForce3ID: return "GeForce 3";
  case kCGLRendererGeForceFXID: return "GeForce FX";
  case kCGLRendererGeForce8xxxID: return "GeForce 8xxx";
  case kCGLRendererGeForceID: return "GeForce";
  case kCGLRendererVTBladeXP2ID: return "VT Blade XP 2";
  case kCGLRendererIntel900ID: return "Intel 900";
  case kCGLRendererIntelX3100ID: return "Intel X3100";
  case kCGLRendererIntelHDID: return "Intel HD";
  case kCGLRendererIntelHD4000ID: return "Intel HD 4000";
  case kCGLRendererIntelHD5000ID: return "Intel HD 5000";
  case kCGLRendererMesa3DFXID: return "Mesa 3DFX";

  default:
    snprintf (renderer_name, sizeof renderer_name, "0x%08x", id & kCGLRendererIDMatchingMask);
    renderer_name[sizeof renderer_name-1] = 0;
    return renderer_name;
  }
}

static GLuint
create_texture (CGLContextObj cgl_context,
                GLuint        target,
                IOSurfaceRef  io_surface,
                guint         width,
                guint         height)
{
  GLuint texture = 0;

  if (!CHECK_GL (NULL, glActiveTexture (GL_TEXTURE0)) ||
      !CHECK_GL (NULL, glGenTextures (1, &texture)) ||
      !CHECK_GL (NULL, glBindTexture (target, texture)) ||
      !CHECK (NULL, CGLTexImageIOSurface2D (cgl_context,
                                            target,
                                            GL_RGBA,
                                            width,
                                            height,
                                            GL_BGRA,
                                            GL_UNSIGNED_INT_8_8_8_8_REV,
                                            io_surface,
                                            0)) ||
      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_BASE_LEVEL, 0)) ||
      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)) ||
      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)) ||
      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)) ||
      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE)) ||
      !CHECK_GL (NULL, glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)) ||
      !CHECK_GL (NULL, glBindTexture (target, 0)))
    {
      glDeleteTextures (1, &texture);
      return 0;
    }

  return texture;
}

static void
gdk_macos_gl_context_allocate (GdkMacosGLContext *self)
{
  GdkSurface *surface;
  GLint opaque;

  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
  g_assert (self->cgl_context != NULL);
  g_assert (self->target != 0);
  g_assert (self->texture != 0 || self->fbo == 0);
  g_assert (self->fbo != 0 || self->texture == 0);

  if (!(surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self))))
    return;

  /* Alter to an opaque surface if necessary */
  opaque = gdk_surface_is_opaque (surface);
  if (opaque != self->last_opaque)
    {
      self->last_opaque = !!opaque;
      if (!CHECK (NULL, CGLSetParameter (self->cgl_context, kCGLCPSurfaceOpacity, &opaque)))
        return;
    }

  if (self->texture == 0)
    {
      GdkMacosBuffer *buffer;
      IOSurfaceRef io_surface;
      guint width;
      guint height;
      GLuint texture = 0;
      GLuint fbo = 0;

      buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
      io_surface = _gdk_macos_buffer_get_native (buffer);
      width = _gdk_macos_buffer_get_width (buffer);
      height = _gdk_macos_buffer_get_height (buffer);

      /* We might need to re-enforce our CGL context here to keep
       * video playing correctly. Something, somewhere, might have
       * changed the context without touching GdkGLContext.
       *
       * Without this, video_player often breaks in gtk-demo when using
       * the GStreamer backend.
       */

      CGLSetCurrentContext (self->cgl_context);

      if (!(texture = create_texture (self->cgl_context, self->target, io_surface, width, height)) ||
          !CHECK_GL (NULL, glGenFramebuffers (1, &fbo)) ||
          !CHECK_GL (NULL, glBindFramebuffer (GL_FRAMEBUFFER, fbo)) ||
          !CHECK_GL (NULL, glBindTexture (self->target, texture)) ||
          !CHECK_GL (NULL, glFramebufferTexture2D (GL_FRAMEBUFFER,
                                                   GL_COLOR_ATTACHMENT0,
                                                   self->target,
                                                   texture,
                                                   0)) ||
          !check_framebuffer_status (GL_FRAMEBUFFER))
        {
          glDeleteFramebuffers (1, &fbo);
          glDeleteTextures (1, &texture);
          return;
        }

      glBindTexture (self->target, 0);
      glBindFramebuffer (GL_FRAMEBUFFER, 0);

      self->texture = texture;
      self->fbo = fbo;
    }
}

static void
gdk_macos_gl_context_release (GdkMacosGLContext *self)
{
  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
  g_assert (self->texture != 0 || self->fbo == 0);
  g_assert (self->fbo != 0 || self->texture == 0);

  glBindFramebuffer (GL_FRAMEBUFFER, 0);
  glActiveTexture (GL_TEXTURE0);
  glBindTexture (self->target, 0);

  if (self->fbo != 0)
    {
      glDeleteFramebuffers (1, &self->fbo);
      self->fbo = 0;
    }

  if (self->texture != 0)
    {
      glDeleteTextures (1, &self->texture);
      self->texture = 0;
    }
}

static CGLPixelFormatObj
create_pixel_format (GdkGLVersion  *version,
                     gboolean      *out_legacy,
                     GError       **error)
{
  CGLPixelFormatAttribute attrs[] = {
    kCGLPFAOpenGLProfile, 0,
    kCGLPFAAllowOfflineRenderers, /* allow sharing across GPUs */
    kCGLPFADepthSize, 0,
    kCGLPFAStencilSize, 0,
    kCGLPFAColorSize, 24,
    kCGLPFAAlphaSize, 8,
    0
  };
  CGLPixelFormatObj format = NULL;
  GLint n_format = 1;

  *out_legacy = FALSE;

  if (gdk_gl_version_get_major (version) >= 4)
    {
      attrs[1] = (CGLPixelFormatAttribute)kCGLOGLPVersion_GL4_Core;
      if (CHECK (error, CGLChoosePixelFormat (attrs, &format, &n_format)))
        return g_steal_pointer (&format);
    }

  if (gdk_gl_version_greater_equal (version, &GDK_GL_MIN_GL_VERSION))
    {
      attrs[1] = (CGLPixelFormatAttribute)kCGLOGLPVersion_GL3_Core;
      if (CHECK (error, CGLChoosePixelFormat (attrs, &format, &n_format)))
        return g_steal_pointer (&format);
    }

  attrs[1] = (CGLPixelFormatAttribute) kCGLOGLPVersion_Legacy;
  if (!CHECK (error, CGLChoosePixelFormat (attrs, &format, &n_format)))
    return NULL;

  *out_legacy = TRUE;

  return g_steal_pointer (&format);
}

static GdkGLAPI
gdk_macos_gl_context_real_realize (GdkGLContext  *context,
                                   GError       **error)
{
  GdkMacosGLContext *self = (GdkMacosGLContext *)context;
  GdkSurface *surface;
  GdkDisplay *display;
  CGLPixelFormatObj pixelFormat;
  CGLContextObj shared_gl_context = nil;
  CGLContextObj cgl_context;
  CGLContextObj existing;
  GdkGLContext *shared;
  GLint sync_to_framerate = 1;
  GLint validate = 0;
  GLint renderer_id = 0;
  GLint swapRect[4];
  GdkGLVersion min_version, version;
  gboolean legacy;

  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));

  if (self->cgl_context != nil)
    return GDK_GL_API_GL;

  if (!gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, error))
    return 0;

  existing = CGLGetCurrentContext ();

  gdk_gl_context_get_matching_version (context,
                                       GDK_GL_API_GL,
                                       FALSE,
                                       &min_version);

  display = gdk_gl_context_get_display (context);
  shared = gdk_display_get_gl_context (display);

  if (shared != NULL)
    {
      if (!(shared_gl_context = GDK_MACOS_GL_CONTEXT (shared)->cgl_context))
        {
          g_set_error_literal (error,
                               GDK_GL_ERROR,
                               GDK_GL_ERROR_NOT_AVAILABLE,
                               "Cannot access shared CGLContextObj");
          return 0;
        }
    }

  GDK_DISPLAY_DEBUG (display, OPENGL,
                     "Creating CGLContextObj (version %d.%d)",
                     gdk_gl_version_get_major (&min_version), gdk_gl_version_get_minor (&min_version));

  if (!(pixelFormat = create_pixel_format (&min_version, &legacy, error)))
    return 0;

  if (!CHECK (error, CGLCreateContext (pixelFormat, shared_gl_context, &cgl_context)))
    {
      CGLReleasePixelFormat (pixelFormat);
      return 0;
    }

  CGLSetCurrentContext (cgl_context);
  CGLReleasePixelFormat (pixelFormat);

  gdk_gl_version_init_epoxy (&version);
  if (!gdk_gl_version_greater_equal (&version, &min_version))
    {
      CGLReleaseContext (cgl_context);
      return 0;
    }

  if (validate)
    CHECK (NULL, CGLEnable (cgl_context, kCGLCEStateValidation));

  if (!CHECK (error, CGLSetParameter (cgl_context, kCGLCPSwapInterval, &sync_to_framerate)) ||
      !CHECK (error, CGLGetParameter (cgl_context, kCGLCPCurrentRendererID, &renderer_id)))
   {
      CGLReleaseContext (cgl_context);
      return 0;
   }

  surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));

  if (surface != NULL)
    {
      /* Setup initial swap rectangle. We might not actually need this
       * anymore though as we are rendering to an IOSurface and we have
       * a scissor clip when rendering to it.
       */

      swapRect[0] = 0;
      swapRect[1] = 0;
      swapRect[2] = surface->width;
      swapRect[3] = surface->height;
      CGLSetParameter (cgl_context, kCGLCPSwapRectangle, swapRect);
      CGLEnable (cgl_context, kCGLCESwapRectangle);
    }

  GDK_DISPLAY_DEBUG (display, OPENGL,
                     "Created CGLContextObj@%p using %s",
                     cgl_context,
                     get_renderer_name (renderer_id));

  gdk_gl_context_set_version (context, &version);
  gdk_gl_context_set_is_legacy (context, legacy);

  self->cgl_context = g_steal_pointer (&cgl_context);

  if (existing != NULL)
    CGLSetCurrentContext (existing);

  return GDK_GL_API_GL;
}

static void
gdk_macos_gl_context_begin_frame (GdkDrawContext  *context,
                                  gpointer         context_data,
                                  GdkMemoryDepth   depth,
                                  cairo_region_t  *region,
                                  GdkColorState  **out_color_state,
                                  GdkMemoryDepth  *out_depth)
{
  GdkMacosGLContext *self = (GdkMacosGLContext *)context;
  GdkMacosBuffer *buffer;
  GdkSurface *surface;

  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));

  surface = gdk_draw_context_get_surface (context);
  buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));

  _gdk_macos_buffer_set_flipped (buffer, TRUE);
  _gdk_macos_buffer_set_damage (buffer, region);

  /* Create our render target and bind it */
  gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
  gdk_macos_gl_context_allocate (self);

  GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, context_data, depth, region, out_color_state, out_depth);

  gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
  CHECK_GL (NULL, glBindFramebuffer (GL_FRAMEBUFFER, self->fbo));
}

static void
gdk_macos_gl_context_end_frame (GdkDrawContext *context,
                                gpointer        context_data,
                                cairo_region_t *painted)
{
  GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
  GdkSurface *surface;
  cairo_rectangle_int_t flush_rect;
  GLint swapRect[4];

  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
  g_assert (self->cgl_context != nil);

  GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->end_frame (context, context_data, painted);

  surface = gdk_draw_context_get_surface (context);
  gdk_gl_context_make_current (GDK_GL_CONTEXT (self));

  /* Coordinates are in display coordinates, where as flush_rect is
  * in GDK coordinates. Must flip Y to match display coordinates where
  * 0,0 is the bottom-left corner.
  */

  cairo_region_get_extents (painted, &flush_rect);
  swapRect[0] = flush_rect.x;                   /* left */
  swapRect[1] = surface->height - flush_rect.y; /* bottom */
  swapRect[2] = flush_rect.width;               /* width */
  swapRect[3] = flush_rect.height;              /* height */
  CGLSetParameter (self->cgl_context, kCGLCPSwapRectangle, swapRect);

  gdk_macos_gl_context_release (self);

  glFlush ();

  /* Begin a Core Animation transaction so that all changes we
   * make within the window are seen atomically.
   */

  [CATransaction begin];
  [CATransaction setDisableActions:YES];
  _gdk_macos_surface_swap_buffers (GDK_MACOS_SURFACE (surface), painted);
  [CATransaction commit];
}

static void
gdk_macos_gl_context_empty_frame (GdkDrawContext *draw_context)
{
}

static void
gdk_macos_gl_context_surface_resized (GdkDrawContext *draw_context)
{
  GdkMacosGLContext *self = (GdkMacosGLContext *)draw_context;

  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));

  if (self->cgl_context != NULL)
    CGLUpdateContext (self->cgl_context);
}


static gboolean
gdk_macos_gl_context_surface_attach (GdkDrawContext  *context,
                                     GError         **error)
{
  GdkSurface *surface = gdk_draw_context_get_surface (context);
  NSView *view = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));

  if (!GDK_IS_MACOS_LAYER ([view layer]))
    {
      [view setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawNever];
      [view setLayer:[GdkMacosLayer layer]];
      [view setWantsLayer:YES];
    }

  return TRUE;
}

static gboolean
gdk_macos_gl_context_clear_current (GdkGLContext *context)
{
  GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);

  g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);

  if (self->cgl_context == CGLGetCurrentContext ())
    {
      glFlush ();
      CGLSetCurrentContext (NULL);
    }

  return TRUE;
}

static gboolean
gdk_macos_gl_context_is_current (GdkGLContext *context)
{
  GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);

  return self->cgl_context == CGLGetCurrentContext ();
}

static gboolean
gdk_macos_gl_context_make_current (GdkGLContext *context,
                                   gboolean      surfaceless)
{
  GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
  CGLContextObj current;

  g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);

  current = CGLGetCurrentContext ();

  if (self->cgl_context != current)
    {
      /* The OpenGL mac programming guide suggests that glFlush() is called
       * before switching current contexts to ensure that the drawing commands
       * are submitted.
       *
       * TODO: investigate if we need this because we may switch contexts
       *       during composition and only need it when returning to a
       *       previous context that uses the other context.
       */

      if (current != NULL)
        glFlush ();

      CGLSetCurrentContext (self->cgl_context);
    }

  return TRUE;
}

static cairo_region_t *
gdk_macos_gl_context_get_damage (GdkGLContext *context)
{
  GdkMacosGLContext *self = (GdkMacosGLContext *)context;
  const cairo_region_t *damage;
  GdkMacosBuffer *buffer;
  GdkSurface *surface;

  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));

  if ((surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context))) &&
      (buffer = GDK_MACOS_SURFACE (surface)->front) &&
      (damage = _gdk_macos_buffer_get_damage (buffer)))
    return cairo_region_copy (damage);

  return GDK_GL_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->get_damage (context);
}

static guint
gdk_macos_gl_context_get_default_framebuffer (GdkGLContext *context)
{
  return GDK_MACOS_GL_CONTEXT (context)->fbo;
}

static void
gdk_macos_gl_context_dispose (GObject *gobject)
{
  GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (gobject);

  self->texture = 0;
  self->fbo = 0;

  if (self->cgl_context != nil)
    {
      CGLContextObj cgl_context = g_steal_pointer (&self->cgl_context);

      if (cgl_context == CGLGetCurrentContext ())
        CGLSetCurrentContext (NULL);

      CGLClearDrawable (cgl_context);
      CGLDestroyContext (cgl_context);
    }

  G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject);
}

static void
gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
  GdkGLContextClass *gl_class = GDK_GL_CONTEXT_CLASS (klass);

  object_class->dispose = gdk_macos_gl_context_dispose;

  draw_context_class->begin_frame = gdk_macos_gl_context_begin_frame;
  draw_context_class->end_frame = gdk_macos_gl_context_end_frame;
  draw_context_class->empty_frame = gdk_macos_gl_context_empty_frame;
  draw_context_class->surface_resized = gdk_macos_gl_context_surface_resized;
  draw_context_class->surface_attach = gdk_macos_gl_context_surface_attach;

  gl_class->get_damage = gdk_macos_gl_context_get_damage;
  gl_class->clear_current = gdk_macos_gl_context_clear_current;
  gl_class->is_current = gdk_macos_gl_context_is_current;
  gl_class->make_current = gdk_macos_gl_context_make_current;
  gl_class->realize = gdk_macos_gl_context_real_realize;
  gl_class->get_default_framebuffer = gdk_macos_gl_context_get_default_framebuffer;

  gl_class->backend_type = GDK_GL_CGL;
}

static void
gdk_macos_gl_context_init (GdkMacosGLContext *self)
{
  self->target = GL_TEXTURE_RECTANGLE;
}

G_GNUC_END_IGNORE_DEPRECATIONS

Messung V0.5 in Prozent
C=98 H=95 G=96

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-07-02) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik