From: malc Date: Sun, 2 Dec 2012 07:36:55 +0000 (+0400) Subject: Try to use pbo if available X-Git-Tag: v14~93 X-Git-Url: https://repo.or.cz/w/llpp.git/commitdiff_plain/12bc2c148a1d265ccc64bfa114a3c914c61297d8 Try to use pbo if available --- diff --git a/link.c b/link.c index 837ab2e..1c384b9 100644 --- a/link.c +++ b/link.c @@ -133,6 +133,7 @@ struct tile { int x, y, w, h; int slicecount; int sliceheight; + struct pbo *pbo; fz_pixmap *pixmap; struct slice slices[1]; }; @@ -227,8 +228,22 @@ struct { void (*freepage) (void *); char *trimcachepath; + + int pbo_usable; + void (*glBindBufferARB) (GLenum, GLuint); + void (*glUnmapBufferARB) (GLenum); + void *(*glMapBufferARB) (GLenum, GLenum); + void (*glBufferDataARB) (GLenum, GLsizei, void *, GLenum); + void (*glGenBuffersARB) (GLsizei, GLuint *); + void (*glDeleteBuffersARB) (GLsizei, GLuint *); } state; +struct pbo { + GLuint id; + void *ptr; + size_t size; +}; + static void UNUSED_ATTR debug_rect (const char *cap, fz_rect r) { printf ("%s(rect) %.2f,%.2f,%.2f,%.2f\n", cap, r.x0, r.y0, r.x1, r.y1); @@ -564,14 +579,16 @@ static void freepage (struct page *page) static void freetile (struct tile *tile) { unlinktile (tile); + if (!tile->pbo) { #ifndef PIGGYBACK - fz_drop_pixmap (state.ctx, tile->pixmap); + fz_drop_pixmap (state.ctx, tile->pixmap); #else - if (state.pig) { - fz_drop_pixmap (state.ctx, state.pig); - } - state.pig = tile->pixmap; + if (state.pig) { + fz_drop_pixmap (state.ctx, state.pig); + } + state.pig = tile->pixmap; #endif + } free (tile); } @@ -778,7 +795,8 @@ static int obscured (struct page *page, fz_bbox bbox) #define OBSCURED(a, b) 0 #endif -static struct tile *rendertile (struct page *page, int x, int y, int w, int h) +static struct tile *rendertile (struct page *page, int x, int y, int w, int h, + struct pbo *pbo) { fz_bbox bbox; fz_device *dev; @@ -808,8 +826,16 @@ static struct tile *rendertile (struct page *page, int x, int y, int w, int h) state.pig = NULL; } if (!tile->pixmap) { - tile->pixmap = - fz_new_pixmap_with_bbox (state.ctx, state.colorspace, bbox); + if (pbo) { + tile->pixmap = + fz_new_pixmap_with_bbox_and_data (state.ctx, state.colorspace, + bbox, pbo->ptr); + tile->pbo = pbo; + } + else { + tile->pixmap = + fz_new_pixmap_with_bbox (state.ctx, state.colorspace, bbox); + } } tile->w = w; @@ -1711,16 +1737,17 @@ static void * mainloop (void *unused) struct page *page; struct tile *tile; double a, b; + void *data; - ret = sscanf (p + 4, " %" FMT_ptr " %d %d %d %d", - FMT_ptr_cast (&page), &x, &y, &w, &h); - if (ret != 5) { + ret = sscanf (p + 4, " %" FMT_ptr " %d %d %d %d %" FMT_ptr, + FMT_ptr_cast (&page), &x, &y, &w, &h, &data); + if (ret != 6) { errx (1, "bad tile line `%.*s' ret=%d", len, p, ret); } lock ("tile"); a = now (); - tile = rendertile (page, x, y, w, h); + tile = rendertile (page, x, y, w, h, data); b = now (); unlock ("tile"); @@ -2086,6 +2113,7 @@ static void uploadslice (struct tile *tile, struct slice *slice) { int offset; struct slice *slice1; + unsigned char *texdata; offset = 0; for (slice1 = tile->slices; slice != slice1; slice1++) { @@ -2116,6 +2144,13 @@ static void uploadslice (struct tile *tile, struct slice *slice) slice->texindex = texindex; glBindTexture (GL_TEXTURE_RECTANGLE_ARB, state.texids[texindex]); + if (tile->pbo) { + state.glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, tile->pbo->id); + texdata = 0; + } + else { + texdata = tile->pixmap->samples; + } if (subimage) { glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, @@ -2125,7 +2160,7 @@ static void uploadslice (struct tile *tile, struct slice *slice) slice->h, state.texform, state.texty, - tile->pixmap->samples+offset + texdata+offset ); } else { @@ -2137,9 +2172,12 @@ static void uploadslice (struct tile *tile, struct slice *slice) 0, state.texform, state.texty, - tile->pixmap->samples+offset + texdata+offset ); } + if (tile->pbo) { + state.glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0); + } } } @@ -3324,6 +3362,135 @@ CAMLprim value ml_cloexec (value fd_v) CAMLreturn (Val_unit); } +CAMLprim value ml_getpbo (value w_v, value h_v, value cs_v) +{ + CAMLparam2 (w_v, h_v); + CAMLlocal1 (ret_v); + struct pbo *pbo; + int w = Int_val (w_v); + int h = Int_val (h_v); + int cs = Int_val (cs_v); + + if (state.pbo_usable) { + pbo = calloc (sizeof (*pbo), 1); + if (!pbo) { + err (1, "calloc pbo"); + } + + switch (cs) { + case 0: + case 1: + pbo->size = w*h*4; + break; + case 2: + pbo->size = w*h*2; + break; + default: + errx (1, "ml_getpbo: invalid colorspace %d", cs); + } + + state.glGenBuffersARB (1, &pbo->id); + state.glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, pbo->id); + state.glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, pbo->size, + NULL, GL_STREAM_DRAW); + pbo->ptr = state.glMapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, + GL_READ_WRITE); + if (!pbo->ptr) { + fprintf (stderr, "glMapBufferARB failed: %#x", glGetError ()); + state.glDeleteBuffersARB (1, &pbo->id); + free (pbo); + ret_v = caml_copy_string ("0"); + } + else { + int res; + char *s; + + res = snprintf (NULL, 0, "%" FMT_ptr, pbo); + if (res < 0) { + err (1, "snprintf %" FMT_ptr " failed", pbo); + } + s = malloc (res+1); + if (!s) { + err (1, "malloc %d bytes failed", res+1); + } + res = sprintf (s, "%" FMT_ptr, pbo); + if (res < 0) { + err (1, "sprintf %" FMT_ptr " failed", pbo); + } + ret_v = caml_copy_string (s); + free (s); + } + state.glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0); + } + else { + ret_v = caml_copy_string ("0"); + } + CAMLreturn (ret_v); +} + +CAMLprim value ml_freepbo (value s_v) +{ + CAMLparam1 (s_v); + char *s = String_val (s_v); + struct tile *tile = parse_pointer ("ml_freepbo", s); + + if (tile->pbo) { + state.glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, tile->pbo->id); + state.glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB); + state.glDeleteBuffersARB (1, &tile->pbo->id); + tile->pbo->id = -1; + tile->pbo->ptr = NULL; + tile->pbo->size = -1; + } + CAMLreturn (Val_unit); +} + +CAMLprim value ml_unmappbo (value s_v) +{ + CAMLparam1 (s_v); + char *s = String_val (s_v); + struct tile *tile = parse_pointer ("ml_unmappbo", s); + + if (tile->pbo) { + state.glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, tile->pbo->id); + state.glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB); + tile->pbo->ptr = NULL; + state.glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0); + } + CAMLreturn (Val_unit); +} + +static void setuppbo (void) +{ +#define GGPA(n) *(void (**) ()) &state.n = glXGetProcAddress ((GLubyte *) #n) + GGPA (glBindBufferARB); + if (state.glBindBufferARB) { + GGPA (glUnmapBufferARB); + if (state.glUnmapBufferARB) { + GGPA (glMapBufferARB); + if (state.glMapBufferARB) { + GGPA (glBufferDataARB); + if (state.glBufferDataARB) { + GGPA (glGenBuffersARB); + if (state.glGenBuffersARB) { + GGPA (glDeleteBuffersARB); + if (state.glDeleteBuffersARB) { + state.pbo_usable = 1; + } + } + } + } + } + } +#undef GGPA +} + +CAMLprim value ml_pbo_usable (value unit_v) +{ + CAMLparam1 (unit_v); + CAMLreturn (Val_bool (state.pbo_usable)); +} + CAMLprim value ml_init (value pipe_v, value params_v) { CAMLparam2 (pipe_v, params_v); @@ -3333,6 +3500,7 @@ CAMLprim value ml_init (value pipe_v, value params_v) char *fontpath; int colorspace; int mustoresize; + int haspboext; struct sigaction sa; state.cr = Int_val (Field (pipe_v, 0)); @@ -3346,6 +3514,7 @@ CAMLprim value ml_init (value pipe_v, value params_v) colorspace = Int_val (Field (params_v, 6)); fontpath = String_val (Field (params_v, 7)); state.trimcachepath = strdup (String_val (Field (params_v, 8))); + haspboext = Bool_val (Field (params_v, 9)); state.ctx = fz_new_context (NULL, NULL, mustoresize); @@ -3371,6 +3540,10 @@ CAMLprim value ml_init (value pipe_v, value params_v) realloctexts (texcount); + if (haspboext) { + setuppbo (); + } + #ifdef __CYGWIN__ sa.sa_handler = SIG_IGN; sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; diff --git a/main.ml b/main.ml index e4d5bb5..3b447e1 100644 --- a/main.ml +++ b/main.ml @@ -16,7 +16,8 @@ let now = Unix.gettimeofday;; type params = (angle * proportional * trimparams * texcount * sliceheight * memsize - * colorspace * fontpath * trimcachepath) + * colorspace * fontpath * trimcachepath + * haspbo) and pageno = int and width = int and height = int @@ -40,6 +41,7 @@ and aalevel = int and irect = (int * int * int * int) and trimparams = (trimmargins * irect) and colorspace = | Rgb | Bgr | Gray +and haspbo = bool ;; type link = @@ -99,6 +101,10 @@ external getlinkcount : opaque -> int = "ml_getlinkcount";; external findpwl: int -> int -> pagewithlinks = "ml_find_page_with_links" external popen : string -> (Unix.file_descr * int) list -> unit = "ml_popen";; external mbtoutf8 : string -> string = "ml_mbtoutf8";; +external getpbo : width -> height -> colorspace -> string = "ml_getpbo";; +external freepbo : string -> unit = "ml_freepbo";; +external unmappbo : string -> unit = "ml_unmappbo";; +external pbousable : unit -> bool = "ml_pbo_usable";; let platform_to_string = function | Punknown -> "unknown" @@ -337,6 +343,7 @@ type conf = ; mutable keyhashes : (string * keyhash) list ; mutable hfsize : int ; mutable pgscale : float + ; mutable usepbo : bool } and columns = | Csingle of singlecolumn @@ -539,6 +546,7 @@ let defconf = ; updatecurs = false ; hfsize = 12 ; pgscale = 1.0 + ; usepbo = false ; keyhashes = let mk n = (n, Hashtbl.create 1) in [ mk "global" @@ -1504,7 +1512,12 @@ let tilepage n p layout = let h = l.pageh - y in min h conf.tileh in - wcmd "tile %s %d %d %d %d" p x y w h; + let pbo = + if conf.usepbo + then getpbo w h conf.colorspace + else "0" + in + wcmd "tile %s %d %d %d %d %s" p x y w h pbo; state.currently <- Tiling ( l, p, conf.colorspace, conf.angle, state.gen, col, row, @@ -2156,6 +2169,7 @@ let gctiles () = ) then Queue.push lruitem state.tilelru else ( + freepbo p; wcmd "freetile %s" p; state.memused <- state.memused - s; state.uioh#infochanged Memused; @@ -2386,6 +2400,7 @@ let act cmds = | Tiling (l, pageopaque, cs, angle, gen, col, row, tilew, tileh) -> vlog "tile %d [%d,%d] took %f sec" l.pageno col row t; + unmappbo opaque; if tilew != conf.tilew || tileh != conf.tileh then ( wcmd "freetile %s" opaque; @@ -4471,6 +4486,11 @@ let enterinfomode = wcmd "cs %d" v; load state.layout; ); + if pbousable () + then + src#bool "use PBO" + (fun () -> conf.usepbo) + (fun v -> conf.usepbo <- v); ); sep (); @@ -6113,6 +6133,7 @@ struct | "update-cursor" -> { c with updatecurs = bool_of_string v } | "hint-font-size" -> { c with hfsize = bound (int_of_string v) 5 100 } | "page-scroll-scale" -> { c with pgscale = float_of_string v } + | "use-pbo" -> { c with usepbo = bool_of_string v } | _ -> c with exn -> prerr_endline ("Error processing attribute (`" ^ @@ -6223,6 +6244,7 @@ struct dst.hfsize <- src.hfsize; dst.hscrollstep <- src.hscrollstep; dst.pgscale <- src.pgscale; + dst.usepbo <- src.usepbo; ;; let get s = @@ -6632,6 +6654,7 @@ struct oi "hint-font-size" c.hfsize dc.hfsize; oi "horizontal-scroll-step" c.hscrollstep dc.hscrollstep; oF "page-scroll-scale" c.pgscale dc.pgscale; + ob "use-pbo" c.usepbo dc.usepbo; ;; let keymapsbuf always dc c = @@ -6967,7 +6990,8 @@ let () = init (cr, cw) ( conf.angle, conf.proportional, (conf.trimmargins, conf.trimfuzz), conf.texcount, conf.sliceheight, conf.mustoresize, conf.colorspace, - !Config.fontpath, !trimcachepath + !Config.fontpath, !trimcachepath, + GlMisc.check_extension "GL_ARB_pixel_buffer_object" ); state.sr <- sr; state.sw <- sw;