why does clearing this skia and glfw canvas result in black instead of transparent if the window is full screen?
I'm trying to use skia-python with glfw to draw various shapes and text onto a transparent floating overlay. I have a small demo working for my purposes, but it behaves differently if the window is created with full screen resolution versus created with anything smaller.
The code here alternates between drawing some red text or a green circle, and attempts to clear the canvas in between using canvas.clear(skia.ColorTRANSPARENT). This behaves exactly as I want if the window is created with dimensions anything less than 1920x1080 (the resolution of my screen). If I create the window with these full screen dimensions, instead of clearing the canvas this call fills the screen with black (and then the rest of the code still works, alternating between text and circle).
import contextlib, glfw, skia
from OpenGL import GL
import time
WIDTH, HEIGHT = 1920, 1080
#WIDTH, HEIGHT = 1919, 1079
@contextlib.contextmanager
def glfw_window():
if not glfw.init():
raise RuntimeError('glfw.init() failed')
glfw.window_hint(glfw.STENCIL_BITS, 8) # ?
glfw.window_hint(glfw.SAMPLES, 14) # ?
glfw.window_hint(glfw.DECORATED, 0)
glfw.window_hint(glfw.TRANSPARENT_FRAMEBUFFER, 1)
glfw.window_hint(glfw.FLOATING, 1)
window = glfw.create_window(WIDTH, HEIGHT, '', None, None)
glfw.make_context_current(window)
yield window
glfw.terminate()
@contextlib.contextmanager
def skia_surface(window):
context = skia.GrDirectContext.MakeGL()
(fb_width, fb_height) = glfw.get_framebuffer_size(window)
backend_render_target = skia.GrBackendRenderTarget(
fb_width,
fb_height,
0, # sampleCnt
0, # stencilBits
skia.GrGLFramebufferInfo(0, GL.GL_RGBA8))
surface = skia.Surface.MakeFromBackendRenderTarget(
context, backend_render_target, skia.kBottomLeft_GrSurfaceOrigin,
skia.kRGBA_8888_ColorType, skia.ColorSpace.MakeSRGB())
assert surface is not None
yield surface
context.abandonContext()
def drawString(canvas):
paint = skia.Paint(AntiAlias=True, Color=skia.ColorRED)
font = skia.Font(skia.Typeface('meiryo'), 36)
canvas.drawString('あかさたな', 100, 100, font, paint)
def drawCircle(canvas):
paint = skia.Paint(Color=skia.ColorGREEN)
canvas.drawCircle(100, 100, 40, paint)
with glfw_window() as window:
GL.glClear(GL.GL_COLOR_BUFFER_BIT)
with skia_surface(window) as surface:
with surface as canvas:
while (glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS
and not glfw.window_should_close(window)):
canvas.clear(skia.ColorTRANSPARENT)
if int(time.time()) % 2 == 0:
drawString(canvas)
else:
drawCircle(canvas)
surface.flushAndSubmit()
glfw.swap_buffers(window)
glfw.poll_events()
#glfw.wait_events()
For the purpose of demonstration, this is the entire working demo. Most of it comes from this skia-python documentation. I think the only packages it needs are glfw (2.5.3), PyOpenGl (3.1.6), and skia-python (87.4)
My actual use case will use a slightly different loop and doesn't need to draw to the screen as frequently as this demo, but it does need to periodically clear the canvas. I don't actually need it to be perfectly full screen, I can use 1919x1079, mostly I'm just curious what's going on here. This is being tested on Windows 10 with Python 3.10 by the way
source https://stackoverflow.com/questions/72588667/why-does-clearing-this-skia-and-glfw-canvas-result-in-black-instead-of-transpare
Comments
Post a Comment